Merge branch 'develop' into plugin-add-run-min-style
This commit is contained in:
@ -5,18 +5,28 @@ LAMMPS has several commands which can be used to invoke Python
|
|||||||
code directly from an input script:
|
code directly from an input script:
|
||||||
|
|
||||||
* :doc:`python <python>`
|
* :doc:`python <python>`
|
||||||
* :doc:`variable python <variable>`
|
* :doc:`python-style variables <variable>`
|
||||||
|
* :doc:`equal-style and atom-style variables with formulas containing Python function wrappers <variable>`
|
||||||
* :doc:`fix python/invoke <fix_python_invoke>`
|
* :doc:`fix python/invoke <fix_python_invoke>`
|
||||||
* :doc:`pair_style python <pair_python>`
|
* :doc:`pair_style python <pair_python>`
|
||||||
|
|
||||||
The :doc:`python <python>` command which can be used to define and
|
The :doc:`python <python>` command can be used to define and execute a
|
||||||
execute a Python function that you write the code for. The Python
|
Python function that you write the code for. The Python function can
|
||||||
function can also be assigned to a LAMMPS python-style variable via
|
also be assigned to a LAMMPS python-style variable via the
|
||||||
the :doc:`variable <variable>` command. Each time the variable is
|
:doc:`variable <variable>` command. Each time the variable is
|
||||||
evaluated, either in the LAMMPS input script itself, or by another
|
evaluated, either in the LAMMPS input script itself, or by another
|
||||||
LAMMPS command that uses the variable, this will trigger the Python
|
LAMMPS command that uses the variable, this will trigger the Python
|
||||||
function to be invoked.
|
function to be invoked.
|
||||||
|
|
||||||
|
The Python function can also be referenced in the formula used to
|
||||||
|
define an :doc:`equal-style or atom-style variable <variable>`, using
|
||||||
|
the syntax for a :doc:`Python function wrapper <variable>`. This make
|
||||||
|
it easy to pass LAMMPS-related arguments to the Python function, as
|
||||||
|
well as to invoke it whenever the equal- or atom-style variable is
|
||||||
|
evaluated. For an atom-style variable it means the Python function
|
||||||
|
can be invoked once per atom, using per-atom properties as arguments
|
||||||
|
to the function.
|
||||||
|
|
||||||
The Python code for the function can be included directly in the input
|
The Python code for the function can be included directly in the input
|
||||||
script or in an auxiliary file. The function can have arguments which
|
script or in an auxiliary file. The function can have arguments which
|
||||||
are mapped to LAMMPS variables (also defined in the input script) and
|
are mapped to LAMMPS variables (also defined in the input script) and
|
||||||
|
|||||||
@ -53,15 +53,17 @@ The value *eng* is the interaction energy for the angle.
|
|||||||
|
|
||||||
The value *v_name* can be used together with the *set* keyword to
|
The value *v_name* can be used together with the *set* keyword to
|
||||||
compute a user-specified function of the angle theta. The *name*
|
compute a user-specified function of the angle theta. The *name*
|
||||||
specified for the *v_name* value is the name of an :doc:`equal-style variable <variable>` which should evaluate a formula based on a
|
specified for the *v_name* value is the name of an :doc:`equal-style
|
||||||
|
variable <variable>` which should evaluate a formula based on a
|
||||||
variable which will store the angle theta. This other variable must
|
variable which will store the angle theta. This other variable must
|
||||||
be an :doc:`internal-style variable <variable>` defined in the input
|
be an :doc:`internal-style variable <variable>` specified by the *set*
|
||||||
script; its initial numeric value can be anything. It must be an
|
keyword. It is an internal-style variable, because this command
|
||||||
internal-style variable, because this command resets its value
|
resets its value directly. The internal-style variable does not need
|
||||||
directly. The *set* keyword is used to identify the name of this
|
to be defined in the input script (though it can be); if it is not
|
||||||
other variable associated with theta.
|
defined, then the *set* option creates an :doc:`internal-style
|
||||||
|
variable <variable>` with the specified name.
|
||||||
|
|
||||||
Note that the value of theta for each angle which stored in the
|
Note that the value of theta for each angle which is stored in the
|
||||||
internal variable is in radians, not degrees.
|
internal variable is in radians, not degrees.
|
||||||
|
|
||||||
As an example, these commands can be added to the bench/in.rhodo
|
As an example, these commands can be added to the bench/in.rhodo
|
||||||
@ -70,7 +72,6 @@ system and output the statistics in various ways:
|
|||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
variable t internal 0.0
|
|
||||||
variable cos equal cos(v_t)
|
variable cos equal cos(v_t)
|
||||||
variable cossq equal cos(v_t)*cos(v_t)
|
variable cossq equal cos(v_t)*cos(v_t)
|
||||||
|
|
||||||
|
|||||||
@ -130,13 +130,15 @@ moving apart.
|
|||||||
|
|
||||||
The value *v_name* can be used together with the *set* keyword to
|
The value *v_name* can be used together with the *set* keyword to
|
||||||
compute a user-specified function of the bond distance. The *name*
|
compute a user-specified function of the bond distance. The *name*
|
||||||
specified for the *v_name* value is the name of an :doc:`equal-style variable <variable>` which should evaluate a formula based on a
|
specified for the *v_name* value is the name of an :doc:`equal-style
|
||||||
variable which will store the bond distance. This other variable must
|
variable <variable>` which should evaluate a formula based on a
|
||||||
be an :doc:`internal-style variable <variable>` defined in the input
|
variable which stores the bond distance. This other variable must be
|
||||||
script; its initial numeric value can be anything. It must be an
|
the :doc:`internal-style variable <variable>` specified by the *set*
|
||||||
internal-style variable, because this command resets its value
|
keyword. It is an internal-style variable, because this command
|
||||||
directly. The *set* keyword is used to identify the name of this
|
resets its value directly. The internal-style variable does not need
|
||||||
other variable associated with theta.
|
to be defined in the input script (though it can be); if it is not
|
||||||
|
defined, then the *set* option creates an :doc:`internal-style
|
||||||
|
variable <variable>` with the specified name.
|
||||||
|
|
||||||
As an example, these commands can be added to the bench/in.rhodo
|
As an example, these commands can be added to the bench/in.rhodo
|
||||||
script to compute the length\ :math:`^2` of every bond in the system and
|
script to compute the length\ :math:`^2` of every bond in the system and
|
||||||
@ -144,7 +146,6 @@ output the statistics in various ways:
|
|||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
variable d internal 0.0
|
|
||||||
variable dsq equal v_d*v_d
|
variable dsq equal v_d*v_d
|
||||||
|
|
||||||
compute 1 all property/local batom1 batom2 btype
|
compute 1 all property/local batom1 batom2 btype
|
||||||
|
|||||||
@ -45,30 +45,31 @@ interactions. The number of datums generated, aggregated across all
|
|||||||
processors, equals the number of dihedral angles in the system, modified
|
processors, equals the number of dihedral angles in the system, modified
|
||||||
by the group parameter as explained below.
|
by the group parameter as explained below.
|
||||||
|
|
||||||
The value *phi* (:math:`\phi`) is the dihedral angle, as defined in the diagram
|
The value *phi* (:math:`\phi`) is the dihedral angle, as defined in
|
||||||
on the :doc:`dihedral_style <dihedral_style>` doc page.
|
the diagram on the :doc:`dihedral_style <dihedral_style>` doc page.
|
||||||
|
|
||||||
The value *v_name* can be used together with the *set* keyword to compute a
|
The value *v_name* can be used together with the *set* keyword to
|
||||||
user-specified function of the dihedral angle :math:`\phi`. The *name*
|
compute a user-specified function of the dihedral angle :math:`\phi`.
|
||||||
specified for the *v_name* value is the name of an
|
The *name* specified for the *v_name* value is the name of an
|
||||||
:doc:`equal-style variable <variable>` which should evaluate a formula based on
|
:doc:`equal-style variable <variable>` which should evaluate a formula
|
||||||
a variable which will store the angle :math:`\phi`. This other variable must
|
based on a variable which will store the angle :math:`\phi`. This
|
||||||
be an :doc:`internal-style variable <variable>` defined in the input
|
other variable must be an :doc:`internal-style variable <variable>`
|
||||||
script; its initial numeric value can be anything. It must be an
|
specified by the *set* keyword. It is an internal-style variable,
|
||||||
internal-style variable, because this command resets its value
|
because this command resets its value directly. The internal-style
|
||||||
directly. The *set* keyword is used to identify the name of this
|
variable does not need to be defined in the input script (though it
|
||||||
other variable associated with :math:`\phi`.
|
can be); if it is not defined, then the *set* option creates an
|
||||||
|
:doc:`internal-style variable <variable>` with the specified name.
|
||||||
|
|
||||||
Note that the value of :math:`\phi` for each angle which stored in the internal
|
Note that the value of :math:`\phi` for each angle which stored in the
|
||||||
variable is in radians, not degrees.
|
internal variable is in radians, not degrees.
|
||||||
|
|
||||||
As an example, these commands can be added to the bench/in.rhodo
|
As an example, these commands can be added to the bench/in.rhodo
|
||||||
script to compute the :math:`\cos\phi` and :math:`\cos^2\phi` of every dihedral
|
script to compute the :math:`\cos\phi` and :math:`\cos^2\phi` of every
|
||||||
angle in the system and output the statistics in various ways:
|
dihedral angle in the system and output the statistics in various
|
||||||
|
ways:
|
||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
variable p internal 0.0
|
|
||||||
variable cos equal cos(v_p)
|
variable cos equal cos(v_p)
|
||||||
variable cossq equal cos(v_p)*cos(v_p)
|
variable cossq equal cos(v_p)*cos(v_p)
|
||||||
|
|
||||||
@ -100,10 +101,10 @@ no consistent ordering of the entries within the local vector or array
|
|||||||
from one timestep to the next. The only consistency that is
|
from one timestep to the next. The only consistency that is
|
||||||
guaranteed is that the ordering on a particular timestep will be the
|
guaranteed is that the ordering on a particular timestep will be the
|
||||||
same for local vectors or arrays generated by other compute commands.
|
same for local vectors or arrays generated by other compute commands.
|
||||||
For example, dihedral output from the
|
For example, dihedral output from the :doc:`compute property/local
|
||||||
:doc:`compute property/local <compute_property_local>` command can be combined
|
<compute_property_local>` command can be combined with data from this
|
||||||
with data from this command and output by the :doc:`dump local <dump>`
|
command and output by the :doc:`dump local <dump>` command in a
|
||||||
command in a consistent way.
|
consistent way.
|
||||||
|
|
||||||
Here is an example of how to do this:
|
Here is an example of how to do this:
|
||||||
|
|
||||||
|
|||||||
@ -416,24 +416,23 @@ atom, based on its coordinates. They apply to all styles except
|
|||||||
*single*. The *name* specified for the *var* keyword is the name of
|
*single*. The *name* specified for the *var* keyword is the name of
|
||||||
an :doc:`equal-style variable <variable>` that should evaluate to a
|
an :doc:`equal-style variable <variable>` that should evaluate to a
|
||||||
zero or non-zero value based on one or two or three variables that
|
zero or non-zero value based on one or two or three variables that
|
||||||
will store the *x*, *y*, or *z* coordinates of an atom (one variable per
|
will store the *x*, *y*, or *z* coordinates of an atom (one variable
|
||||||
coordinate). If used, these other variables must be
|
per coordinate). If used, these other variables must be specified by
|
||||||
:doc:`internal-style variables <variable>` defined in the input
|
the *set* keyword. They are internal-style variable, because this
|
||||||
script; their initial numeric value can be anything. They must be
|
command resets their values directly. The internal-style variables do
|
||||||
internal-style variables, because this command resets their values
|
not need to be defined in the input script (though they can be); if
|
||||||
directly. The *set* keyword is used to identify the names of these
|
one (or more) is not defined, then the *set* option creates an
|
||||||
other variables, one variable for the *x*-coordinate of a created atom,
|
:doc:`internal-style variable <variable>` with the specified name.
|
||||||
one for *y*, and one for *z*.
|
|
||||||
|
|
||||||
.. figure:: img/sinusoid.jpg
|
.. figure:: img/sinusoid.jpg
|
||||||
:figwidth: 50%
|
:figwidth: 50%
|
||||||
:align: right
|
:align: right
|
||||||
:target: _images/sinusoid.jpg
|
:target: _images/sinusoid.jpg
|
||||||
|
|
||||||
When an atom is created, its :math:`(x,y,z)` coordinates become the values for
|
When an atom is about to be created, its :math:`(x,y,z)` coordinates
|
||||||
any *set* variable that is defined. The *var* variable is then
|
become the values for any *set* variable that is defined. The *var*
|
||||||
evaluated. If the returned value is 0.0, the atom is not created. If
|
variable is then evaluated. If the returned value is 0.0, the atom is
|
||||||
it is non-zero, the atom is created.
|
not created. If it is non-zero, the atom is created.
|
||||||
|
|
||||||
As an example, these commands can be used in a 2d simulation, to
|
As an example, these commands can be used in a 2d simulation, to
|
||||||
create a sinusoidal surface. Note that the surface is "rough" due to
|
create a sinusoidal surface. Note that the surface is "rough" due to
|
||||||
@ -456,8 +455,6 @@ converts lattice spacings to distance.
|
|||||||
region box block 0 $x 0 $y -0.5 0.5
|
region box block 0 $x 0 $y -0.5 0.5
|
||||||
create_box 1 box
|
create_box 1 box
|
||||||
|
|
||||||
variable xx internal 0.0
|
|
||||||
variable yy internal 0.0
|
|
||||||
variable v equal "(0.2*v_y*ylat * cos(v_xx/xlat * 2.0*PI*4.0/v_x) + 0.5*v_y*ylat - v_yy) > 0.0"
|
variable v equal "(0.2*v_y*ylat * cos(v_xx/xlat * 2.0*PI*4.0/v_x) + 0.5*v_y*ylat - v_yy) > 0.0"
|
||||||
create_atoms 1 box var v set x xx set y yy
|
create_atoms 1 box var v set x xx set y yy
|
||||||
write_dump all atom sinusoid.lammpstrj
|
write_dump all atom sinusoid.lammpstrj
|
||||||
|
|||||||
@ -98,52 +98,53 @@ the following dynamic equation:
|
|||||||
|
|
||||||
\frac{dc}{dt} = -\alpha (K_p e + K_i \int_0^t e \, dt + K_d \frac{de}{dt} )
|
\frac{dc}{dt} = -\alpha (K_p e + K_i \int_0^t e \, dt + K_d \frac{de}{dt} )
|
||||||
|
|
||||||
where *c* is the continuous time analog of the control variable,
|
where *c* is the continuous time analog of the control variable, *e*
|
||||||
*e* =\ *pvar*\ -\ *setpoint* is the error in the process variable, and
|
=\ *pvar*\ -\ *setpoint* is the error in the process variable, and
|
||||||
:math:`\alpha`, :math:`K_p`, :math:`K_i` , and :math:`K_d` are constants
|
:math:`\alpha`, :math:`K_p`, :math:`K_i` , and :math:`K_d` are
|
||||||
set by the corresponding
|
constants set by the corresponding keywords described above. The
|
||||||
keywords described above. The discretized version of this equation is:
|
discretized version of this equation is:
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
|
|
||||||
c_n = c_{n-1} -\alpha \left( K_p \tau e_n + K_i \tau^2 \sum_{i=1}^n e_i + K_d (e_n - e_{n-1}) \right)
|
c_n = c_{n-1} -\alpha \left( K_p \tau e_n + K_i \tau^2 \sum_{i=1}^n e_i + K_d (e_n - e_{n-1}) \right)
|
||||||
|
|
||||||
where :math:`\tau = \mathtt{Nevery} \cdot \mathtt{timestep}` is the time
|
where :math:`\tau = \mathtt{Nevery} \cdot \mathtt{timestep}` is the
|
||||||
interval between updates,
|
time interval between updates, and the subscripted variables indicate
|
||||||
and the subscripted variables indicate the values of *c* and *e* at
|
the values of *c* and *e* at successive updates.
|
||||||
successive updates.
|
|
||||||
|
|
||||||
From the first equation, it is clear that if the three gain values
|
From the first equation, it is clear that if the three gain values
|
||||||
:math:`K_p`, :math:`K_i`, :math:`K_d` are dimensionless constants,
|
:math:`K_p`, :math:`K_i`, :math:`K_d` are dimensionless constants,
|
||||||
then :math:`\alpha` must have
|
then :math:`\alpha` must have units of [unit *cvar*\ ]/[unit *pvar*\
|
||||||
units of [unit *cvar*\ ]/[unit *pvar*\ ]/[unit time] e.g. [ eV/K/ps
|
]/[unit time] e.g. [ eV/K/ps ]. The advantage of this unit scheme is
|
||||||
]. The advantage of this unit scheme is that the value of the
|
that the value of the constants should be invariant under a change of
|
||||||
constants should be invariant under a change of either the MD timestep
|
either the MD timestep size or the value of *Nevery*\ . Similarly, if
|
||||||
size or the value of *Nevery*\ . Similarly, if the LAMMPS :doc:`unit style <units>` is changed, it should only be necessary to change
|
the LAMMPS :doc:`unit style <units>` is changed, it should only be
|
||||||
the value of :math:`\alpha` to reflect this, while leaving :math:`K_p`,
|
necessary to change the value of :math:`\alpha` to reflect this, while
|
||||||
:math:`K_i`, and :math:`K_d` unaltered.
|
leaving :math:`K_p`, :math:`K_i`, and :math:`K_d` unaltered.
|
||||||
|
|
||||||
When choosing the values of the four constants, it is best to first
|
When choosing the values of the four constants, it is best to first
|
||||||
pick a value and sign for :math:`\alpha` that is consistent with the
|
pick a value and sign for :math:`\alpha` that is consistent with the
|
||||||
magnitudes and signs of *pvar* and *cvar*\ . The magnitude of :math:`K_p`
|
magnitudes and signs of *pvar* and *cvar*\ . The magnitude of
|
||||||
should then be tested over a large positive range keeping :math:`K_i = K_d =0`.
|
:math:`K_p` should then be tested over a large positive range keeping
|
||||||
A good value for :math:`K_p` will produce a fast response in *pvar*,
|
:math:`K_i = K_d =0`. A good value for :math:`K_p` will produce a
|
||||||
without overshooting the *setpoint*\ . For many applications, proportional
|
fast response in *pvar*, without overshooting the *setpoint*\ . For
|
||||||
feedback is sufficient, and so :math:`K_i = K_d =0` can be used. In cases
|
many applications, proportional feedback is sufficient, and so
|
||||||
where there is a substantial lag time in the response of *pvar* to a change
|
:math:`K_i = K_d =0` can be used. In cases where there is a
|
||||||
in *cvar*, this can be counteracted by increasing :math:`K_d`. In situations
|
substantial lag time in the response of *pvar* to a change in *cvar*,
|
||||||
|
this can be counteracted by increasing :math:`K_d`. In situations
|
||||||
where *pvar* plateaus without reaching *setpoint*, this can be
|
where *pvar* plateaus without reaching *setpoint*, this can be
|
||||||
counteracted by increasing :math:`K_i`. In the language of Charles Dickens,
|
counteracted by increasing :math:`K_i`. In the language of Charles
|
||||||
:math:`K_p` represents the error of the present, :math:`K_i` the error of
|
Dickens, :math:`K_p` represents the error of the present, :math:`K_i`
|
||||||
the past, and :math:`K_d` the error yet to come.
|
the error of the past, and :math:`K_d` the error yet to come.
|
||||||
|
|
||||||
Because this fix updates *cvar*, but does not initialize its value,
|
Because this fix updates *cvar*, but does not initialize its value,
|
||||||
the initial value :math:`c_0` is that assigned by the user in the input script via
|
the initial value :math:`c_0` is that assigned by the user in the
|
||||||
the :doc:`internal-style variable <variable>` command. This value is
|
input script via the :doc:`internal-style variable <variable>`
|
||||||
used (by every other LAMMPS command that uses the variable) until this
|
command. This value is used (by every other LAMMPS command that uses
|
||||||
fix performs its first update of *cvar* after *Nevery* timesteps. On
|
the variable) until this fix performs its first update of *cvar* after
|
||||||
the first update, the value of the derivative term is set to zero,
|
*Nevery* timesteps. On the first update, the value of the derivative
|
||||||
because the value of :math:`e_{n-1}` is not yet defined.
|
term is set to zero, because the value of :math:`e_{n-1}` is not yet
|
||||||
|
defined.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -154,21 +155,23 @@ must produce a global quantity, not a per-atom or local quantity.
|
|||||||
|
|
||||||
If *pvar* begins with "c\_", a compute ID must follow which has been
|
If *pvar* begins with "c\_", a compute ID must follow which has been
|
||||||
previously defined in the input script and which generates a global
|
previously defined in the input script and which generates a global
|
||||||
scalar or vector. See the individual :doc:`compute <compute>` doc page
|
scalar or vector. See the individual :doc:`compute <compute>` doc
|
||||||
for details. If no bracketed integer is appended, the scalar
|
page for details. If no bracketed integer is appended, the scalar
|
||||||
calculated by the compute is used. If a bracketed integer is
|
calculated by the compute is used. If a bracketed integer is
|
||||||
appended, the Ith value of the vector calculated by the compute is
|
appended, the Ith value of the vector calculated by the compute is
|
||||||
used. Users can also write code for their own compute styles and :doc:`add them to LAMMPS <Modify>`.
|
used. Users can also write code for their own compute styles and
|
||||||
|
:doc:`add them to LAMMPS <Modify>`.
|
||||||
|
|
||||||
If *pvar* begins with "f\_", a fix ID must follow which has been
|
If *pvar* begins with "f\_", a fix ID must follow which has been
|
||||||
previously defined in the input script and which generates a global
|
previously defined in the input script and which generates a global
|
||||||
scalar or vector. See the individual :doc:`fix <fix>` page for
|
scalar or vector. See the individual :doc:`fix <fix>` page for
|
||||||
details. Note that some fixes only produce their values on certain
|
details. Note that some fixes only produce their values on certain
|
||||||
timesteps, which must be compatible with when fix controller
|
timesteps, which must be compatible with when fix controller
|
||||||
references the values, or else an error results. If no bracketed integer
|
references the values, or else an error results. If no bracketed
|
||||||
is appended, the scalar calculated by the fix is used. If a bracketed
|
integer is appended, the scalar calculated by the fix is used. If a
|
||||||
integer is appended, the Ith value of the vector calculated by the fix
|
bracketed integer is appended, the Ith value of the vector calculated
|
||||||
is used. Users can also write code for their own fix style and :doc:`add them to LAMMPS <Modify>`.
|
by the fix is used. Users can also write code for their own fix style
|
||||||
|
and :doc:`add them to LAMMPS <Modify>`.
|
||||||
|
|
||||||
If *pvar* begins with "v\_", a variable name must follow which has been
|
If *pvar* begins with "v\_", a variable name must follow which has been
|
||||||
previously defined in the input script. Only equal-style variables
|
previously defined in the input script. Only equal-style variables
|
||||||
@ -182,19 +185,21 @@ variable.
|
|||||||
The target value *setpoint* for the process variable must be a numeric
|
The target value *setpoint* for the process variable must be a numeric
|
||||||
value, in whatever units *pvar* is defined for.
|
value, in whatever units *pvar* is defined for.
|
||||||
|
|
||||||
The control variable *cvar* must be the name of an :doc:`internal-style variable <variable>` previously defined in the input script. Note
|
The control variable *cvar* must be the name of an
|
||||||
that it is not specified with a "v\_" prefix, just the name of the
|
:doc:`internal-style variable <variable>` previously defined in the
|
||||||
variable. It must be an internal-style variable, because this fix
|
input script. Note that it is not specified with a "v\_" prefix, just
|
||||||
updates its value directly. Note that other commands can use an
|
the name of the variable. It must be an internal-style variable,
|
||||||
equal-style versus internal-style variable interchangeably.
|
because this fix updates its value directly. Note that other commands
|
||||||
|
can use an equal-style versus internal-style variable interchangeably.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Restart, fix_modify, output, run start/stop, minimize info
|
Restart, fix_modify, output, run start/stop, minimize info
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
Currently, no information about this fix is written to :doc:`binary restart files <restart>`. None of the :doc:`fix_modify <fix_modify>` options
|
Currently, no information about this fix is written to :doc:`binary
|
||||||
are relevant to this fix.
|
restart files <restart>`. None of the :doc:`fix_modify <fix_modify>`
|
||||||
|
options are relevant to this fix.
|
||||||
|
|
||||||
This fix produces a global vector with 3 values which can be accessed
|
This fix produces a global vector with 3 values which can be accessed
|
||||||
by various :doc:`output commands <Howto_output>`. The values can be
|
by various :doc:`output commands <Howto_output>`. The values can be
|
||||||
@ -211,7 +216,8 @@ variable is in. The vector values calculated by this fix are
|
|||||||
"extensive".
|
"extensive".
|
||||||
|
|
||||||
No parameter of this fix can be used with the *start/stop* keywords of
|
No parameter of this fix can be used with the *start/stop* keywords of
|
||||||
the :doc:`run <run>` command. This fix is not invoked during :doc:`energy minimization <minimize>`.
|
the :doc:`run <run>` command. This fix is not invoked during
|
||||||
|
:doc:`energy minimization <minimize>`.
|
||||||
|
|
||||||
Restrictions
|
Restrictions
|
||||||
""""""""""""
|
""""""""""""
|
||||||
|
|||||||
@ -225,22 +225,25 @@ rotated configuration of the molecule.
|
|||||||
|
|
||||||
.. versionadded:: 21Nov2023
|
.. versionadded:: 21Nov2023
|
||||||
|
|
||||||
The *var* and *set* keywords can be used together to provide a criterion
|
The *var* and *set* keywords can be used together to provide a
|
||||||
for accepting or rejecting the addition of an individual atom, based on its
|
criterion for accepting or rejecting the addition of an individual
|
||||||
coordinates. The *name* specified for the *var* keyword is the name of an
|
atom, based on its coordinates. The *name* specified for the *var*
|
||||||
:doc:`equal-style variable <variable>` that should evaluate to a zero or
|
keyword is the name of an :doc:`equal-style variable <variable>` that
|
||||||
non-zero value based on one or two or three variables that will store the
|
should evaluate to a zero or non-zero value based on one or two or
|
||||||
*x*, *y*, or *z* coordinates of an atom (one variable per coordinate). If
|
three variables that will store the *x*, *y*, or *z* coordinates of an
|
||||||
used, these other variables must be :doc:`internal-style variables
|
atom (one variable per coordinate). If used, these other variables
|
||||||
<variable>` defined in the input script; their initial numeric value can be
|
must be :doc:`internal-style variables <variable>` specified by the
|
||||||
anything. They must be internal-style variables, because this command
|
*set* keyword. They must be internal-style variables, because this
|
||||||
resets their values directly. The *set* keyword is used to identify the
|
command resets their values directly. The internal-style variables do
|
||||||
names of these other variables, one variable for the *x*-coordinate of a
|
not need to be defined in the input script (though they can be); if
|
||||||
created atom, one for *y*, and one for *z*. When an atom is created, its
|
one (or more) is not defined, then the *set* option creates an
|
||||||
:math:`(x,y,z)` coordinates become the values for any *set* variable that
|
:doc:`internal-style variable <variable>` with the specified name.
|
||||||
is defined. The *var* variable is then evaluated. If the returned value
|
|
||||||
is 0.0, the atom is not created. If it is non-zero, the atom is created.
|
When an atom is about to be created, its :math:`(x,y,z)` coordinates
|
||||||
For an example of how to use these keywords, see the
|
become the values for any *set* variable that is defined. The *var*
|
||||||
|
variable is then evaluated. If the returned value is 0.0, the atom is
|
||||||
|
not created. If it is non-zero, the atom is created. For an example
|
||||||
|
of how to use the set/var keywords in a similar context, see the
|
||||||
:doc:`create_atoms <create_atoms>` command.
|
:doc:`create_atoms <create_atoms>` command.
|
||||||
|
|
||||||
The *rate* option moves the insertion volume in the z direction (3d)
|
The *rate* option moves the insertion volume in the z direction (3d)
|
||||||
@ -304,12 +307,13 @@ units of distance or velocity.
|
|||||||
Restart, fix_modify, output, run start/stop, minimize info
|
Restart, fix_modify, output, run start/stop, minimize info
|
||||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
This fix writes the state of the deposition to :doc:`binary restart files <restart>`. This includes information about how many
|
This fix writes the state of the deposition to :doc:`binary restart
|
||||||
particles have been deposited, the random number generator seed, the
|
files <restart>`. This includes information about how many particles
|
||||||
next timestep for deposition, etc. See the
|
have been deposited, the random number generator seed, the next
|
||||||
:doc:`read_restart <read_restart>` command for info on how to re-specify
|
timestep for deposition, etc. See the :doc:`read_restart
|
||||||
a fix in an input script that reads a restart file, so that the
|
<read_restart>` command for info on how to re-specify a fix in an
|
||||||
operation of the fix continues in an uninterrupted fashion.
|
input script that reads a restart file, so that the operation of the
|
||||||
|
fix continues in an uninterrupted fashion.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|||||||
@ -10,43 +10,46 @@ Syntax
|
|||||||
|
|
||||||
python mode keyword args ...
|
python mode keyword args ...
|
||||||
|
|
||||||
* mode = *source* or name of Python function
|
* mode = *source* or *name* of Python function
|
||||||
|
|
||||||
if mode is *source*:
|
if mode is *source*:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
|
||||||
keyword = *here* or name of a *Python file*
|
keyword = *here* or name of a *Python file*
|
||||||
*here* arg = inline
|
*here* arg = one or more lines of Python code
|
||||||
inline = one or more lines of Python code which defines func
|
must be a single argument, typically enclosed between triple quotes
|
||||||
must be a single argument, typically enclosed between triple quotes
|
the in-lined Python code will be executed immediately
|
||||||
*Python file* = name of a file with Python code which will be executed immediately
|
*Python file* = name of a file with Python code which will be executed immediately
|
||||||
|
|
||||||
* if *mode* is the name of a Python function, one or more keywords with/without arguments must be appended
|
* if *mode* is *name* of a Python function:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
|
||||||
|
one or more keywords with/without arguments must be appended
|
||||||
keyword = *invoke* or *input* or *return* or *format* or *length* or *file* or *here* or *exists*
|
keyword = *invoke* or *input* or *return* or *format* or *length* or *file* or *here* or *exists*
|
||||||
*invoke* arg = none = invoke the previously defined Python function
|
*invoke* arg = invoke the previously-defined Python function
|
||||||
|
logreturn = log return value of the invoked python function, if defined (optional)
|
||||||
*input* args = N i1 i2 ... iN
|
*input* args = N i1 i2 ... iN
|
||||||
N = # of inputs to function
|
N = # of inputs to function
|
||||||
i1,...,iN = value, SELF, or LAMMPS variable name
|
i1,...,iN = value, SELF, or LAMMPS variable name
|
||||||
value = integer number, floating point number, or string
|
value = integer number, floating point number, or string
|
||||||
SELF = reference to LAMMPS itself which can be accessed by Python function
|
SELF = reference to LAMMPS itself which can then be accessed by Python function
|
||||||
variable = v_name, where name = name of LAMMPS variable, e.g. v_abc
|
variable = v_name, where name = name of a LAMMPS variable, e.g. v_abc
|
||||||
|
internal variable = iv_name, where name = name of a LAMMPS internal-style variable, e.g. iv_xyz
|
||||||
*return* arg = varReturn
|
*return* arg = varReturn
|
||||||
varReturn = v_name = LAMMPS variable name which the return value of the Python function will be assigned to
|
varReturn = v_name = LAMMPS variable name which the return value of the Python function will be assigned to
|
||||||
*format* arg = fstring with M characters
|
*format* arg = fstring with M characters
|
||||||
M = N if no return value, where N = # of inputs
|
M = N if no return value, where N = # of inputs
|
||||||
M = N+1 if there is a return value
|
M = N+1 if there is a return value
|
||||||
fstring = each character (i,f,s,p) corresponds in order to an input or return value
|
fstring = each character (i,f,s,p) corresponds (in order) to an input or return value
|
||||||
'i' = integer, 'f' = floating point, 's' = string, 'p' = SELF
|
'i' = integer, 'f' = floating point, 's' = string, 'p' = SELF
|
||||||
*length* arg = Nlen
|
*length* arg = Nlen
|
||||||
Nlen = max length of string returned from Python function
|
Nlen = max length of string returned from Python function
|
||||||
*file* arg = filename
|
*file* arg = filename
|
||||||
filename = file of Python code, which defines func
|
filename = file of Python code, which defines the Python function
|
||||||
*here* arg = inline
|
*here* arg = inline
|
||||||
inline = one or more lines of Python code which defines func
|
inline = one or more lines of Python code which defines the Python function
|
||||||
must be a single argument, typically enclosed between triple quotes
|
must be a single argument, typically enclosed between triple quotes
|
||||||
*exists* arg = none = Python code has been loaded by previous python command
|
*exists* arg = none = Python code has been loaded by previous python command
|
||||||
|
|
||||||
@ -56,7 +59,7 @@ Examples
|
|||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
python pForce input 2 v_x 20.0 return v_f format fff file force.py
|
python pForce input 2 v_x 20.0 return v_f format fff file force.py
|
||||||
python pForce invoke
|
python pForce invoke logreturn
|
||||||
|
|
||||||
python factorial input 1 myN return v_fac format ii here """
|
python factorial input 1 myN return v_fac format ii here """
|
||||||
def factorial(n):
|
def factorial(n):
|
||||||
@ -87,37 +90,42 @@ Examples
|
|||||||
Description
|
Description
|
||||||
"""""""""""
|
"""""""""""
|
||||||
|
|
||||||
The *python* command allows interfacing LAMMPS with an embedded Python
|
The *python* command interfaces LAMMPS with an embedded Python
|
||||||
interpreter and enables either executing arbitrary python code in that
|
interpreter and enables executing arbitrary python code in that
|
||||||
interpreter, registering a Python function for future execution (as a
|
interpreter. This can be done immediately, by using *mode* = *source*.
|
||||||
python style variable, from a fix interfaced with python, or for direct
|
Or execution can be deferred, by registering a Python function for later
|
||||||
invocation), or invoking such a previously registered function.
|
execution, by using *mode* = *name* of a Python function.
|
||||||
|
|
||||||
Arguments, including LAMMPS variables, can be passed to the function
|
Later execution can be triggered in one of two ways. One is to use the
|
||||||
from the LAMMPS input script and a value returned by the Python function
|
python command again with its *invoke* keyword. The other is to trigger
|
||||||
assigned to a LAMMPS variable. The Python code for the function can be included
|
the evaluation of a python-style, equal-style, vector-style, or
|
||||||
directly in the input script or in a separate Python file. The function
|
atom-style variable. A python-style variable invokes its associated
|
||||||
can be standard Python code or it can make "callbacks" to LAMMPS through
|
Python function; its return value becomes the value of the python-style
|
||||||
its library interface to query or set internal values within LAMMPS.
|
variable. Equal-, vector-, and atom-style variables can use a Python
|
||||||
This is a powerful mechanism for performing complex operations in a
|
function wrapper in their formulas which encodes the Python function
|
||||||
LAMMPS input script that are not possible with the simple input script
|
name, and specifies arguments to pass to the function.
|
||||||
and variable syntax which LAMMPS defines. Thus your input script can
|
|
||||||
operate more like a true programming language.
|
Note that python-style, equal-style, vector-style, and atom-style
|
||||||
|
variables can be used in many different ways within LAMMPS. They can be
|
||||||
|
evaluated directly in an input script, effectively replacing the
|
||||||
|
variable with its value. Or they can be passed to various commands as
|
||||||
|
arguments, so that the variable is evaluated multiple times during a
|
||||||
|
simulation run. See the :doc:`variable <variable>` command doc page for
|
||||||
|
more details on variable styles which enable Python function evaluation.
|
||||||
|
|
||||||
|
The Python code for the function can be included directly in the input
|
||||||
|
script or in a separate Python file. The function can be standard
|
||||||
|
Python code or it can make "callbacks" to LAMMPS through its library
|
||||||
|
interface to query or set internal values within LAMMPS. This is a
|
||||||
|
powerful mechanism for performing complex operations in a LAMMPS input
|
||||||
|
script that are not possible with the simple input script and variable
|
||||||
|
syntax which LAMMPS defines. Thus your input script can operate more
|
||||||
|
like a true programming language.
|
||||||
|
|
||||||
Use of this command requires building LAMMPS with the PYTHON package
|
Use of this command requires building LAMMPS with the PYTHON package
|
||||||
which links to the Python library so that the Python interpreter is
|
which links to the Python library so that the Python interpreter is
|
||||||
embedded in LAMMPS. More details about this process are given below.
|
embedded in LAMMPS. More details about this process are given below.
|
||||||
|
|
||||||
There are two ways to invoke a Python function once it has been
|
|
||||||
registered. One is using the *invoke* keyword. The other is to assign
|
|
||||||
the function to a :doc:`python-style variable <variable>` defined in
|
|
||||||
your input script. Whenever the variable is evaluated, it will execute
|
|
||||||
the Python function to assign a value to the variable. Note that
|
|
||||||
variables can be evaluated in many different ways within LAMMPS. They
|
|
||||||
can be substituted with their result directly in an input script, or
|
|
||||||
they can be passed to various commands as arguments, so that the
|
|
||||||
variable is evaluated during a simulation run.
|
|
||||||
|
|
||||||
A broader overview of how Python can be used with LAMMPS is given in the
|
A broader overview of how Python can be used with LAMMPS is given in the
|
||||||
:doc:`Use Python with LAMMPS <Python_head>` section of the
|
:doc:`Use Python with LAMMPS <Python_head>` section of the
|
||||||
documentation. There also is an ``examples/python`` directory which
|
documentation. There also is an ``examples/python`` directory which
|
||||||
@ -125,69 +133,128 @@ illustrates use of the python command.
|
|||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
The first argument of the *python* command is either the *source*
|
The first argument is the *mode* setting, which is either *source* or
|
||||||
keyword or the name of a Python function. This defines the mode
|
the *name* of a Python function.
|
||||||
of the python command.
|
|
||||||
|
|
||||||
.. versionchanged:: 22Dec2022
|
.. versionchanged:: 22Dec2022
|
||||||
|
|
||||||
If the *source* keyword is used, it is followed by either a file name or
|
If *source* is used, it is followed by either the *here* keyword or a
|
||||||
the *here* keyword. No other keywords can be used. The *here* keyword
|
file name containing Python code. The *here* keyword is followed by a
|
||||||
is followed by a string with python commands, either on a single line
|
string containing python commands, either on a single line enclosed in
|
||||||
enclosed in quotes, or as multiple lines enclosed in triple quotes.
|
quotes, or as multiple lines enclosed in triple quotes. In either
|
||||||
These Python commands will be passed to the python interpreter and
|
case, the in-line code or file contents are passed to the python
|
||||||
executed immediately without registering a Python function for future
|
interpreter and executed immediately. The code will be loaded into
|
||||||
execution. The code will be loaded into and run in the "main" module of
|
and run in the "main" module of the Python interpreter. This allows
|
||||||
the Python interpreter. This allows running arbitrary Python code at
|
running arbitrary Python code at any time while processing the SPARTA
|
||||||
any time while processing the LAMMPS input file. This can be used to
|
input file. This can be used to pre-load Python modules, initialize
|
||||||
pre-load Python modules, initialize global variables, define functions
|
global variables, define functions or classes, or perform operations
|
||||||
or classes, or perform operations using the python programming language.
|
using the Python programming language. The Python code will be
|
||||||
The Python code will be executed in parallel on all MPI processes. No
|
executed in parallel on all the MPI processes being used to run
|
||||||
arguments can be passed.
|
LAMMPS. Note that no arguments can be passed to the executed Python
|
||||||
|
code.
|
||||||
|
|
||||||
|
If the *mode* setting is the *name* of a Python function, then it will
|
||||||
|
be registered with SPARTA for future execution (or already be defined,
|
||||||
|
see the *exists* keyword). One or more keywords must follow the
|
||||||
|
*mode* function name. One of the keywords must be *invoke*, *file*,
|
||||||
|
*here*, or *exists*.
|
||||||
|
|
||||||
In all other cases, the first argument is the name of a Python function
|
In all other cases, the first argument is the name of a Python function
|
||||||
that will be registered with LAMMPS for future execution. The function
|
that will be registered with LAMMPS for future execution. The function
|
||||||
may already be defined (see *exists* keyword) or must be defined using
|
may already be defined (see *exists* keyword) or must be defined using
|
||||||
the *file* or *here* keywords as explained below.
|
the *file* or *here* keywords as explained below.
|
||||||
|
|
||||||
If the *invoke* keyword is used, no other keywords can be used, and a
|
If the *invoke* keyword is used, only the optional *logreturn* keyword
|
||||||
previous *python* command must have registered the Python function
|
can be used. A previous *python* command must have registered the
|
||||||
referenced by this command. This invokes the Python function with the
|
Python function referenced by this command. The command invokes the
|
||||||
previously defined arguments and the return value is processed as
|
Python function with the previously defined arguments. A return value
|
||||||
explained below. You can invoke the function as many times as you wish
|
of the Python function will be ignored unless the Python function is
|
||||||
in your input script.
|
linked to a :doc:`python style variable <variable>` with the *return*
|
||||||
|
keyword. This return value can be logged to the screen and logfile by
|
||||||
|
adding the *logreturn* keyword to the *invoke* command. In that case a
|
||||||
|
message with the name of the python command and the return value is
|
||||||
|
printed. Return values of python functions are otherwise only
|
||||||
|
accessible when the function is invoked indirectly by expanding a
|
||||||
|
:doc:`python style variable <variable>`. You can invoke a registered
|
||||||
|
function as many times as you wish in your input script.
|
||||||
|
|
||||||
The *input* keyword defines how many arguments *N* the Python function
|
The *input* keyword defines how many arguments *N* the Python function
|
||||||
expects. If it takes no arguments, then the *input* keyword should not
|
expects. If it takes no arguments, then the *input* keyword should
|
||||||
be used. Each argument can be specified directly as a value, e.g. '6'
|
not be used. Each argument can be specified directly as a value,
|
||||||
or '3.14159' or 'abc' (a string of characters). The type of each
|
e.g. '6' or '3.14159' or 'abc' (a string of characters). The type of
|
||||||
argument is specified by the *format* keyword as explained below, so
|
each argument is specified by the *format* keyword as explained below,
|
||||||
that Python will know how to interpret the value. If the word SELF is
|
so that Python will know how to interpret the value. If the word SELF
|
||||||
used for an argument it has a special meaning. A pointer is passed to
|
is used for an argument it has a special meaning. A pointer is passed
|
||||||
the Python function which it can convert into a reference to LAMMPS
|
to the Python function which it can convert into a reference to LAMMPS
|
||||||
itself using the :doc:`LAMMPS Python module <Python_module>`. This
|
itself using the :doc:`LAMMPS Python module <Python_module>`. This
|
||||||
enables the function to call back to LAMMPS through its library
|
enables the function to call back to LAMMPS through its library
|
||||||
interface as explained below. This allows the Python function to query
|
interface as explained below. This allows the Python function to
|
||||||
or set values internal to LAMMPS which can affect the subsequent
|
query or set values internal to LAMMPS which can affect the subsequent
|
||||||
execution of the input script. A LAMMPS variable can also be used as an
|
execution of the input script.
|
||||||
argument, specified as v_name, where "name" is the name of the variable.
|
|
||||||
Any style of LAMMPS variable returning a scalar or a string can be used,
|
A LAMMPS variable can also be used as an *input* argument, specified
|
||||||
as defined by the :doc:`variable <variable>` command. The *format*
|
as v_name, where "name" is the name of the variable defined in the
|
||||||
keyword must be used to set the type of data that is passed to Python.
|
input script. Any style of LAMMPS variable returning a scalar or a
|
||||||
|
string can be used, as defined by the :doc:`variable <variable>`
|
||||||
|
command. The style of variable must be consistent with the *format*
|
||||||
|
keyword specification for the type of data that is passed to Python.
|
||||||
Each time the Python function is invoked, the LAMMPS variable is
|
Each time the Python function is invoked, the LAMMPS variable is
|
||||||
evaluated and its value is passed to the Python function.
|
evaluated and its value is passed as an argument to the Python
|
||||||
|
function. Note that a python-style variable can be used as an
|
||||||
|
argument, which means that the a Python function can use arguments
|
||||||
|
which invoke other Python functions.
|
||||||
|
|
||||||
|
A LAMMPS internal-style variable can also be used as an *input*
|
||||||
|
argument, specified as iv_name, where "name" is the name of the
|
||||||
|
internal-style variable. The internal-style variable does not have to
|
||||||
|
be defined in the input script (though it can be); if it is not
|
||||||
|
defined, this command creates an :doc:`internal-style variable
|
||||||
|
<variable>` with the specified name.
|
||||||
|
|
||||||
|
An internal-style variable must be used when an equal-style,
|
||||||
|
vector-style, or atom-style variable triggers the invocation of the
|
||||||
|
Python function defined by this command, by including a Python function
|
||||||
|
wrapper with arguments in its formula. Each of the arguments must be
|
||||||
|
specified as an internal-style variable via the *input* keyword.
|
||||||
|
|
||||||
|
In brief, the syntax for a Python function wrapper in a variable formula
|
||||||
|
is ``py_varname(arg1,arg2,...argN)``, where "varname" is the name of a
|
||||||
|
python-style variable associated with a Python function defined by this
|
||||||
|
command. One or more arguments to the function wrapper can themselves
|
||||||
|
be sub-formulas which the variable command will evaluate and pass as
|
||||||
|
arguments to the Python function. This is done by assigning the numeric
|
||||||
|
result for each argument to an internal-style variable; thus the *input*
|
||||||
|
keyword must specify the arguments as internal-style variables and their
|
||||||
|
format (see below) as "f" for floating point. This is because LAMMPS
|
||||||
|
variable formulas are calculated with floating point arithmetic (any
|
||||||
|
integer values are converted to floating point). Note that the Python
|
||||||
|
function can also have additional inputs, also specified by the *input*
|
||||||
|
keyword, which are NOT arguments in the Python function wrapper. See
|
||||||
|
the example below for the ``mixedargs`` Python function.
|
||||||
|
|
||||||
|
See the :doc:`variable <variable>` command doc page for full details
|
||||||
|
on formula syntax including for Python function wrappers. Examples
|
||||||
|
using Python function wrappers are shown below. Note that as
|
||||||
|
explained above with python-style variables, Python function wrappers
|
||||||
|
can be nested; a sub-formula for an argument can contain its own
|
||||||
|
Python function wrapper which invokes another Python function.
|
||||||
|
|
||||||
The *return* keyword is only needed if the Python function returns a
|
The *return* keyword is only needed if the Python function returns a
|
||||||
value. The specified *varReturn* must be of the form v_name, where
|
value. The specified *varReturn* is of the form v_name, where "name"
|
||||||
"name" is the name of a python-style LAMMPS variable, defined by the
|
is the name of a python-style LAMMPS variable, defined by the
|
||||||
:doc:`variable <variable>` command. The Python function can return a
|
:doc:`variable <variable>` command. The Python function can return a
|
||||||
numeric or string value, as specified by the *format* keyword.
|
numeric or string value, as specified by the *format* keyword.
|
||||||
|
This return value is *only* accessible when expanding the python-style
|
||||||
|
variable. When the *invoke* keyword is used, the return value of
|
||||||
|
the python function is ignored.
|
||||||
|
|
||||||
As explained on the :doc:`variable <variable>` doc page, the definition
|
----------
|
||||||
of a python-style variable associates a Python function name with the
|
|
||||||
variable. This must match the *Python function name* first argument of
|
As explained on the :doc:`variable <variable>` doc page, the
|
||||||
the *python* command. For example these two commands would be
|
definition of a python-style variable associates a Python function
|
||||||
consistent:
|
name with the variable. Its specification must match the *mode*
|
||||||
|
argument of the *python* command for the Python function name. For
|
||||||
|
example these two commands would be consistent:
|
||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
@ -196,43 +263,43 @@ consistent:
|
|||||||
|
|
||||||
The two commands can appear in either order in the input script so
|
The two commands can appear in either order in the input script so
|
||||||
long as both are specified before the Python function is invoked for
|
long as both are specified before the Python function is invoked for
|
||||||
the first time. Afterwards, the variable 'foo' is associated with
|
the first time.
|
||||||
the Python function 'myMultiply'.
|
|
||||||
|
|
||||||
The *format* keyword must be used if the *input* or *return* keywords
|
The *format* keyword must be used if the *input* or *return* keywords
|
||||||
are used. It defines an *fstring* with M characters, where M = sum of
|
are used. It defines an *fstring* with M characters, where M = sum of
|
||||||
number of inputs and outputs. The order of characters corresponds to
|
number of inputs and outputs. The order of characters corresponds to
|
||||||
the N inputs, followed by the return value (if it exists). Each
|
the N inputs, followed by the return value (if it exists). Each
|
||||||
character must be one of the following: "i" for integer, "f" for
|
character must be one of the following: "i" for integer, "f" for
|
||||||
floating point, "s" for string, or "p" for SELF. Each character defines
|
floating point, "s" for string, or "p" for SELF. Each character
|
||||||
the type of the corresponding input or output value of the Python
|
defines the type of the corresponding input or output value of the
|
||||||
function and affects the type conversion that is performed internally as
|
Python function and affects the type conversion that is performed
|
||||||
data is passed back and forth between LAMMPS and Python. Note that it
|
internally as data is passed back and forth between LAMMPS and Python.
|
||||||
is permissible to use a :doc:`python-style variable <variable>` in a
|
Note that it is permissible to use a :doc:`python-style variable
|
||||||
LAMMPS command that allows for an equal-style variable as an argument,
|
<variable>` in a LAMMPS command that allows for an equal-style
|
||||||
but only if the output of the Python function is flagged as a numeric
|
variable as an argument, but only if the output of the Python function
|
||||||
value ("i" or "f") via the *format* keyword.
|
is flagged as a numeric value ("i" or "f") via the *format* keyword.
|
||||||
|
|
||||||
If the *return* keyword is used and the *format* keyword specifies the
|
If the *return* keyword is used and the *format* keyword specifies the
|
||||||
output as a string, then the default maximum length of that string is
|
output as a string, then the default maximum length of that string is
|
||||||
63 characters (64-1 for the string terminator). If you want to return
|
63 characters (64-1 for the string terminator). If you want to return
|
||||||
a longer string, the *length* keyword can be specified with its *Nlen*
|
a longer string, the *length* keyword can be specified with its *Nlen*
|
||||||
value set to a larger number (the code allocates space for Nlen+1 to
|
value set to a larger number. LAMMPS will then allocate Nlen+1 space
|
||||||
include the string terminator). If the Python function generates a
|
to include the string terminator. If the Python function generates a
|
||||||
string longer than the default 63 or the specified *Nlen*, it will be
|
string longer than the default 63 or the specified *Nlen*, it will be
|
||||||
truncated.
|
truncated.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Either the *file*, *here*, or *exists* keyword must be used, but only
|
As noted above, either the *invoke*, *file*, *here*, or *exists*
|
||||||
one of them. These keywords specify what Python code to load into the
|
keyword must be used, but only one of them. These keywords specify
|
||||||
Python interpreter. The *file* keyword gives the name of a file
|
what Python code to load into the Python interpreter. The *file*
|
||||||
containing Python code, which should end with a ".py" suffix. The code
|
keyword gives the name of a file containing Python code, which should
|
||||||
will be immediately loaded into and run in the "main" module of the
|
end with a ".py" suffix. The code will be immediately loaded into and
|
||||||
Python interpreter. The Python code will be executed in parallel on all
|
run in the "main" module of the Python interpreter. The Python code
|
||||||
MPI processes. Note that Python code which contains a function
|
will be executed in parallel on all MPI processes. Note that Python
|
||||||
definition does not "execute" the function when it is run; it simply
|
code which contains a function definition does not "execute" the
|
||||||
defines the function so that it can be invoked later.
|
function when it is run; it simply defines the function so that it can
|
||||||
|
be invoked later.
|
||||||
|
|
||||||
The *here* keyword does the same thing, except that the Python code
|
The *here* keyword does the same thing, except that the Python code
|
||||||
follows as a single argument to the *here* keyword. This can be done
|
follows as a single argument to the *here* keyword. This can be done
|
||||||
@ -243,15 +310,18 @@ proper indentation, blank lines, and comments, as desired. See the
|
|||||||
how triple quotes can be used as part of input script syntax.
|
how triple quotes can be used as part of input script syntax.
|
||||||
|
|
||||||
The *exists* keyword takes no argument. It means that Python code
|
The *exists* keyword takes no argument. It means that Python code
|
||||||
containing the required Python function with the given name has already
|
containing the required Python function with the given name has
|
||||||
been executed, for example by a *python source* command or in the same
|
already been executed, for example by a *python source* command or in
|
||||||
file that was used previously with the *file* keyword.
|
the same file that was used previously with the *file* keyword. This
|
||||||
|
allows use of a single file of Python code which contains multiple
|
||||||
|
functions, any of which can be used in the same (or different) input
|
||||||
|
scripts (see below).
|
||||||
|
|
||||||
Note that the Python code that is loaded and run must contain a function
|
Note that the Python code that is loaded and run by the *file* or
|
||||||
with the specified function name. To operate properly when later
|
*here* keyword must contain a function with the specified function
|
||||||
invoked, the function code must match the *input* and *return* and
|
name. To operate properly when later invoked, the function code must
|
||||||
*format* keywords specified by the python command. Otherwise Python
|
match the *input* and *return* and *format* keywords specified by the
|
||||||
will generate an error.
|
python command. Otherwise Python will generate an error.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -308,13 +378,13 @@ previous value is simply returned, without re-computing it. The
|
|||||||
"global" statement inside the Python function allows it to overwrite the
|
"global" statement inside the Python function allows it to overwrite the
|
||||||
global variables from within the local context of the function.
|
global variables from within the local context of the function.
|
||||||
|
|
||||||
Note that if you load Python code multiple times (via multiple python
|
Also note that if you load Python code multiple times (via multiple
|
||||||
commands), you can overwrite previously loaded variables and functions
|
python commands), you can overwrite previously loaded variables and
|
||||||
if you are not careful. E.g. if the code above were loaded twice, the
|
functions if you are not careful. E.g. if the code above were loaded
|
||||||
global variables would be re-initialized, which might not be what you
|
twice, the global variables would be re-initialized, which might not
|
||||||
want. Likewise, if a function with the same name exists in two chunks
|
be what you want. Likewise, if a function with the same name exists
|
||||||
of Python code you load, the function loaded second will override the
|
in two chunks of Python code you load, the function loaded second will
|
||||||
function loaded first.
|
override the function loaded first.
|
||||||
|
|
||||||
It's important to realize that if you are running LAMMPS in parallel,
|
It's important to realize that if you are running LAMMPS in parallel,
|
||||||
each MPI task will load the Python interpreter and execute a local
|
each MPI task will load the Python interpreter and execute a local
|
||||||
@ -325,15 +395,16 @@ This implies three important things.
|
|||||||
First, if you put a print or other statement creating output to the
|
First, if you put a print or other statement creating output to the
|
||||||
screen in your Python function, you will see P copies of the output,
|
screen in your Python function, you will see P copies of the output,
|
||||||
when running on P processors. If the prints occur at (nearly) the same
|
when running on P processors. If the prints occur at (nearly) the same
|
||||||
time, the P copies of the output may be mixed together. When loading
|
time, the P copies of the output may be mixed together.
|
||||||
the LAMMPS Python module into the embedded Python interpreter, it is
|
|
||||||
possible to pass the pointer to the current LAMMPS class instance and
|
It is possible to avoid this issue, by passing the pointer to the
|
||||||
via the Python interface to the LAMMPS library interface, it is possible
|
current LAMMPS class instance to the Python function via the {input}
|
||||||
to determine the MPI rank of the current process and thus adapt the
|
SELF argument described above. The Python function can then use the
|
||||||
Python code so that output will only appear on MPI rank 0. The
|
Python interface to the LAMMPS library interface, and determine the
|
||||||
following LAMMPS input demonstrates how this could be done. The text
|
MPI rank of the current process. The Python code can then ensure
|
||||||
'Hello, LAMMPS!' should be printed only once, even when running LAMMPS
|
output will only appear on MPI rank 0. The following LAMMPS input
|
||||||
in parallel.
|
demonstrates how this could be done. The text 'Hello, LAMPS!' should
|
||||||
|
be printed only once, even when running LAMMPS in parallel.
|
||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
@ -348,13 +419,13 @@ in parallel.
|
|||||||
|
|
||||||
python python_hello invoke
|
python python_hello invoke
|
||||||
|
|
||||||
If your Python code loads Python modules that are not pre-loaded by the
|
Second, if your Python code loads Python modules that are not
|
||||||
Python library, then it will load the module from disk. This may be a
|
pre-loaded by the Python library, then it will load the module from
|
||||||
bottleneck if 1000s of processors try to load a module at the same time.
|
disk. This may be a bottleneck if 1000s of processors try to load a
|
||||||
On some large supercomputers, loading of modules from disk by Python may
|
module at the same time. On some large supercomputers, loading of
|
||||||
be disabled. In this case you would need to pre-build a Python library
|
modules from disk by Python may be disabled. In this case you would
|
||||||
that has the required modules pre-loaded and link LAMMPS with that
|
need to pre-build a Python library that has the required modules
|
||||||
library.
|
pre-loaded and link LAMMPS with that library.
|
||||||
|
|
||||||
Third, if your Python code calls back to LAMMPS (discussed in the
|
Third, if your Python code calls back to LAMMPS (discussed in the
|
||||||
next section) and causes LAMMPS to perform an MPI operation requires
|
next section) and causes LAMMPS to perform an MPI operation requires
|
||||||
@ -365,10 +436,10 @@ LAMMPS. Otherwise the code may hang.
|
|||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Your Python function can "call back" to LAMMPS through its
|
As mentioned above, a Python function can "call back" to LAMMPS
|
||||||
library interface, if you use the SELF input to pass Python
|
through its library interface, if the SELF input is used to pass
|
||||||
a pointer to LAMMPS. The mechanism for doing this in your
|
Python a pointer to LAMMPS. The mechanism for doing this is as
|
||||||
Python function is as follows:
|
follows:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -416,7 +487,7 @@ which loads and runs the following function from ``examples/python/funcs.py``:
|
|||||||
|
|
||||||
lmp.set_variable("cut",cut) # set a variable in LAMMPS
|
lmp.set_variable("cut",cut) # set a variable in LAMMPS
|
||||||
lmp.command("pair_style lj/cut ${cut}") # LAMMPS command
|
lmp.command("pair_style lj/cut ${cut}") # LAMMPS command
|
||||||
#lmp.command("pair_style lj/cut %d" % cut) # LAMMPS command option
|
#lmp.command("pair_style lj/cut %d" % cut) # alternate form of LAMMPS command
|
||||||
|
|
||||||
lmp.command("pair_coeff * * 1.0 1.0") # ditto
|
lmp.command("pair_coeff * * 1.0 1.0") # ditto
|
||||||
lmp.command("run 10") # ditto
|
lmp.command("run 10") # ditto
|
||||||
@ -449,9 +520,9 @@ is a useful way for a Python function to return multiple values to
|
|||||||
LAMMPS, more than the single value that can be passed back via a
|
LAMMPS, more than the single value that can be passed back via a
|
||||||
return statement. This cutoff value in the "cut" variable is then
|
return statement. This cutoff value in the "cut" variable is then
|
||||||
substituted (by LAMMPS) in the pair_style command that is executed
|
substituted (by LAMMPS) in the pair_style command that is executed
|
||||||
next. Alternatively, the "LAMMPS command option" line could be used
|
next. Alternatively, the "alternate form of LAMMPS command" line
|
||||||
in place of the 2 preceding lines, to have Python insert the value
|
could be used in place of the 2 preceding lines, to have Python insert
|
||||||
into the LAMMPS command string.
|
the value into the LAMMPS command string.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -463,20 +534,128 @@ into the LAMMPS command string.
|
|||||||
file() functions, so long as the command would work if it were
|
file() functions, so long as the command would work if it were
|
||||||
executed in the LAMMPS input script directly at the same point.
|
executed in the LAMMPS input script directly at the same point.
|
||||||
|
|
||||||
However, a Python function can also be invoked during a run, whenever
|
|
||||||
an associated LAMMPS variable it is assigned to is evaluated. If the
|
|
||||||
variable is an input argument to another LAMMPS command (e.g. :doc:`fix setforce <fix_setforce>`), then the Python function will be invoked
|
|
||||||
inside the class for that command, in one of its methods that is
|
|
||||||
invoked in the middle of a timestep. You cannot execute arbitrary
|
|
||||||
input script commands from the Python function (again, via the
|
|
||||||
command() or file() functions) at that point in the run and expect it
|
|
||||||
to work. Other library functions such as those that invoke computes
|
|
||||||
or other variables may have hidden side effects as well. In these
|
|
||||||
cases, LAMMPS has no simple way to check that something illogical is
|
|
||||||
being attempted.
|
|
||||||
|
|
||||||
The same applies to Python functions called during a simulation run at
|
----------
|
||||||
each time step using :doc:`fix python/invoke <fix_python_invoke>`.
|
|
||||||
|
A Python function can also be invoked during a run, whenever
|
||||||
|
an associated python-style variable it is assigned to is evaluated.
|
||||||
|
|
||||||
|
If the variable is an input argument to another LAMMPS command
|
||||||
|
(e.g. :doc:`fix setforce <fix_setforce>`), then the Python function
|
||||||
|
will be invoked inside the class for that command, possibly in one of
|
||||||
|
its methods that is invoked in the middle of a timestep. You cannot
|
||||||
|
execute arbitrary input script commands from the Python function
|
||||||
|
(again, via the command() or file() functions) at that point in the
|
||||||
|
run and expect it to work. Other library functions such as those that
|
||||||
|
invoke computes or other variables may have hidden side effects as
|
||||||
|
well. In these cases, LAMMPS has no simple way to check that
|
||||||
|
something illogical is being attempted.
|
||||||
|
|
||||||
|
The same constraints apply to Python functions called during a
|
||||||
|
simulation run at each time step using the :doc:`fix python/invoke
|
||||||
|
<fix_python_invoke>` command.
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
A Python function can also be invoked within the formula for an
|
||||||
|
equal-style, vector-style, or atom-style variable. This means the
|
||||||
|
Python function will be invoked whenever the variable is invoked. In
|
||||||
|
the case of a vector-style variable, the Python function can be invoked
|
||||||
|
once per element of the global vector. In the case of an atom-style
|
||||||
|
variable, the Python function can be invoked once per atom.
|
||||||
|
|
||||||
|
Here are three simple examples using equal-, vector-, and atom-style
|
||||||
|
variables to trigger execution of a Python function:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
variable foo python truncate
|
||||||
|
python truncate return v_foo input 1 iv_arg format fi here """
|
||||||
|
def truncate(x):
|
||||||
|
return int(x)
|
||||||
|
"""
|
||||||
|
variable ptrunc equal py_foo(press)
|
||||||
|
print "TRUNCATED pressure = ${ptrunc}"
|
||||||
|
|
||||||
|
The Python ``truncate`` function simply converts a floating-point value
|
||||||
|
to an integer value. When the LAMMPS print command evaluates the
|
||||||
|
equal-style ``ptrunc`` variable, the current thermodynamic pressure is
|
||||||
|
passed to the Python function. The truncated value is output to the
|
||||||
|
screen and logfile by the print command. Note that the *input*
|
||||||
|
keyword for the *python* command, specifies an internal-style variable
|
||||||
|
named "arg" as iv_arg which is required to invoke the Python function
|
||||||
|
from a Python function wrapper.
|
||||||
|
|
||||||
|
The last 2 lines can be replaced by these to define a vector-style
|
||||||
|
variable which invokes the same Python ``truncate`` function:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
compute ke all temp
|
||||||
|
variable ke vector c_ke
|
||||||
|
variable ketrunc vector py_foo(v_ke)
|
||||||
|
thermo_style custom step temp epair v_ketrunc[*6]
|
||||||
|
|
||||||
|
The vector-style variable ``ketrunc`` invokes the Python ``truncate``
|
||||||
|
function on each of the 6 components of the global kinetic energy tensor
|
||||||
|
calculated by the :doc:`compute ke <compute_ke>` command. The 6
|
||||||
|
truncated values will be printed with thermo output to the screen and
|
||||||
|
log file.
|
||||||
|
|
||||||
|
Or the last 2 lines of the equal-style variable example can be replaced
|
||||||
|
by these to define atom-style variables which invoke the same Python
|
||||||
|
``truncate`` function:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
variable xtrunc atom py_foo(x)
|
||||||
|
variable ytrunc atom py_foo(y)
|
||||||
|
variable ztrunc atom py_foo(z)
|
||||||
|
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
|
||||||
|
When the dump command invokes the 3 atom-style variables, their
|
||||||
|
arguments x,y,z to the Python function wrapper are the current per-atom
|
||||||
|
coordinates of each atom. The Python ``truncate`` function is thus
|
||||||
|
invoked 3 times for each atom, and the truncated coordinate values for
|
||||||
|
each atom are written to the dump file.
|
||||||
|
|
||||||
|
Note that when using a Python function wrapper in a variable, arguments
|
||||||
|
can be passed to the Python function either from the variable formula or
|
||||||
|
by *input* keyword to the :doc:`python command <python>`. For example,
|
||||||
|
consider these (made up) commands:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
variable foo python mixedargs
|
||||||
|
python mixedargs return v_foo input 6 7.5 v_myValue iv_arg1 iv_argy iv_argz v_flag &
|
||||||
|
format fffffsf here """
|
||||||
|
def mixedargs(a,b,x,y,z,flag):
|
||||||
|
...
|
||||||
|
return result
|
||||||
|
"""
|
||||||
|
variable flag string optionABC
|
||||||
|
variable myValue equal "2.0*temp*c_pe"
|
||||||
|
compute pe all pe
|
||||||
|
compute peatom all pe/atom
|
||||||
|
variable field atom py_foo(x+3.0,sqrt(y),(z-zlo)*c_peatom)
|
||||||
|
|
||||||
|
They define a Python ``mixedargs`` function with 6 arguments. Three of
|
||||||
|
them are internal-style variables, which the variable formula calculates
|
||||||
|
as numeric values for each atom and passes to the function. In this
|
||||||
|
example, these arguments are themselves small formulas containing the
|
||||||
|
x,y,z coordinates of each atom as well as a per-atom compute (c_peratom)
|
||||||
|
and thermodynamic keyword (zlo).
|
||||||
|
|
||||||
|
The other three arguments ``(7.5,v_myValue,v_flag)`` are defined by the
|
||||||
|
*python* command. The first and last are constant values ("7.5" and the
|
||||||
|
``optionABC`` string). The second argument (``myValue``) is the result
|
||||||
|
of an equal-style variable formula which accesses the system temperature
|
||||||
|
and potential energy.
|
||||||
|
|
||||||
|
The "result" returned by each invocation of the Python ``mixedargs``
|
||||||
|
function becomes the per-atom value in the atom-style "field" variable,
|
||||||
|
which could be output to a dump file or used elsewhere in the input
|
||||||
|
script.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -563,27 +742,30 @@ If you use Python code which calls back to LAMMPS, via the SELF input
|
|||||||
argument explained above, there is an extra step required when building
|
argument explained above, there is an extra step required when building
|
||||||
LAMMPS. LAMMPS must also be built as a shared library and your Python
|
LAMMPS. LAMMPS must also be built as a shared library and your Python
|
||||||
function must be able to load the :doc:`"lammps" Python module
|
function must be able to load the :doc:`"lammps" Python module
|
||||||
<Python_module>` that wraps the LAMMPS library interface. These are the
|
<Python_module>` that wraps the LAMMPS library interface.
|
||||||
same steps required to use Python by itself to wrap LAMMPS. Details on
|
|
||||||
these steps are explained on the :doc:`Python <Python_head>` doc page.
|
These are the same steps required to use Python by itself to wrap
|
||||||
Note that it is important that the stand-alone LAMMPS executable and the
|
LAMMPS. Details on these steps are explained on the :doc:`Python
|
||||||
LAMMPS shared library be consistent (built from the same source code
|
<Python_head>` doc page. Note that it is important that the
|
||||||
files) in order for this to work. If the two have been built at
|
stand-alone LAMMPS executable and the LAMMPS shared library be
|
||||||
different times using different source files, problems may occur.
|
consistent (built from the same source code files) in order for this
|
||||||
|
to work. If the two have been built at different times using
|
||||||
|
different source files, problems may occur.
|
||||||
|
|
||||||
Another limitation of calling back to Python from the LAMMPS module
|
Another limitation of calling back to Python from the LAMMPS module
|
||||||
using the *python* command in a LAMMPS input is that both, the Python
|
using the *python* command in a LAMMPS input is that both, the Python
|
||||||
interpreter and LAMMPS, must be linked to the same Python runtime as a
|
interpreter and LAMMPS, must be linked to the same Python runtime as a
|
||||||
shared library. If the Python interpreter is linked to Python
|
shared library. If the Python interpreter is linked to Python
|
||||||
statically (which seems to happen with Conda) then loading the shared
|
statically (which seems to happen with Conda) then loading the shared
|
||||||
LAMMPS library will create a second python "main" module that hides the
|
LAMMPS library will create a second python "main" module that hides
|
||||||
one from the Python interpreter and all previous defined function and
|
the one from the Python interpreter and all previous defined function
|
||||||
global variables will become invisible.
|
and global variables will become invisible.
|
||||||
|
|
||||||
Related commands
|
Related commands
|
||||||
""""""""""""""""
|
""""""""""""""""
|
||||||
|
|
||||||
:doc:`shell <shell>`, :doc:`variable <variable>`, :doc:`fix python/invoke <fix_python_invoke>`
|
:doc:`shell <shell>`, :doc:`variable <variable>`,
|
||||||
|
:doc:`fix python/invoke <fix_python_invoke>`
|
||||||
|
|
||||||
Default
|
Default
|
||||||
"""""""
|
"""""""
|
||||||
|
|||||||
@ -45,7 +45,8 @@ Syntax
|
|||||||
*universe* args = one or more strings
|
*universe* args = one or more strings
|
||||||
*world* args = one string for each partition of processors
|
*world* args = one string for each partition of processors
|
||||||
|
|
||||||
*equal* or *vector* or *atom* args = one formula containing numbers, thermo keywords, math operations, built-in functions, atom values and vectors, compute/fix/variable references
|
*equal* or *vector* or *atom* args = one formula containing numbers, thermo keywords,
|
||||||
|
math operations, built-in functions, atom values and vectors, compute/fix/variable references
|
||||||
numbers = 0.0, 100, -5.4, 2.8e-4, etc
|
numbers = 0.0, 100, -5.4, 2.8e-4, etc
|
||||||
constants = PI, version, on, off, true, false, yes, no
|
constants = PI, version, on, off, true, false, yes, no
|
||||||
thermo keywords = vol, ke, press, etc from :doc:`thermo_style <thermo_style>`
|
thermo keywords = vol, ke, press, etc from :doc:`thermo_style <thermo_style>`
|
||||||
@ -67,8 +68,12 @@ Syntax
|
|||||||
bound(group,dir,region), gyration(group,region), ke(group,reigon),
|
bound(group,dir,region), gyration(group,region), ke(group,reigon),
|
||||||
angmom(group,dim,region), torque(group,dim,region),
|
angmom(group,dim,region), torque(group,dim,region),
|
||||||
inertia(group,dimdim,region), omega(group,dim,region)
|
inertia(group,dimdim,region), omega(group,dim,region)
|
||||||
special functions = sum(x), min(x), max(x), ave(x), trap(x), slope(x), sort(x), rsort(x), gmask(x), rmask(x), grmask(x,y), next(x), is_file(name), is_os(name), extract_setting(name), label2type(kind,label), is_typelabel(kind,label), is_timeout()
|
special functions = sum(x), min(x), max(x), ave(x), trap(x), slope(x), sort(x), rsort(x), \ gmask(x), rmask(x), grmask(x,y), next(x), is_file(name), is_os(name),
|
||||||
feature functions = is_available(category,feature), is_active(category,feature), is_defined(category,id)
|
extract_setting(name), label2type(kind,label),
|
||||||
|
is_typelabel(kind,label), is_timeout()
|
||||||
|
feature functions = is_available(category,feature), is_active(category,feature),
|
||||||
|
is_defined(category,id)
|
||||||
|
python function wrapper = py_varname(x,y,z,...)
|
||||||
atom value = id[i], mass[i], type[i], mol[i], x[i], y[i], z[i], vx[i], vy[i], vz[i], fx[i], fy[i], fz[i], q[i]
|
atom value = id[i], mass[i], type[i], mol[i], x[i], y[i], z[i], vx[i], vy[i], vz[i], fx[i], fy[i], fz[i], q[i]
|
||||||
atom vector = id, mass, type, mol, radius, q, x, y, z, vx, vy, vz, fx, fy, fz
|
atom vector = id, mass, type, mol, radius, q, x, y, z, vx, vy, vz, fx, fy, fz
|
||||||
custom atom property = i_name, d_name, i_name[i], d_name[i], i2_name[i], d2_name[i], i2_name[i][j], d2_name[i][j]
|
custom atom property = i_name, d_name, i_name[i], d_name[i], i2_name[i], d2_name[i], i2_name[i][j], d2_name[i][j]
|
||||||
@ -127,18 +132,21 @@ command), or used as input to an averaging fix (see the :doc:`fix
|
|||||||
ave/time <fix_ave_time>` command). Variables of style *vector* store
|
ave/time <fix_ave_time>` command). Variables of style *vector* store
|
||||||
a formula which produces a vector of such values which can be used as
|
a formula which produces a vector of such values which can be used as
|
||||||
input to various averaging fixes, or elements of which can be part of
|
input to various averaging fixes, or elements of which can be part of
|
||||||
thermodynamic output. Variables of style *atom* store a formula which
|
thermodynamic output.
|
||||||
when evaluated produces one numeric value per atom which can be output
|
|
||||||
to a dump file (see the :doc:`dump custom <dump>` command) or used as
|
Variables of style *atom* store a formula which when evaluated
|
||||||
input to an averaging fix (see the :doc:`fix ave/chunk
|
produces one numeric value per atom which can be output to a dump file
|
||||||
<fix_ave_chunk>` and :doc:`fix ave/atom <fix_ave_atom>` commands).
|
(see the :doc:`dump custom <dump>` command) or used as input to an
|
||||||
Variables of style *atomfile* can be used anywhere in an input script
|
averaging fix (see the :doc:`fix ave/chunk <fix_ave_chunk>` and
|
||||||
that atom-style variables are used; they get their per-atom values
|
:doc:`fix ave/atom <fix_ave_atom>` commands). Variables of style
|
||||||
from a file rather than from a formula. Variables of style *python*
|
*atomfile* can be used anywhere in an input script that atom-style
|
||||||
can be hooked to Python functions using code you provide, so that the
|
variables are used; they get their per-atom values from a file rather
|
||||||
variable gets its value from the evaluation of the Python code.
|
than from a formula.
|
||||||
Variables of style *internal* are used by a few commands which set
|
|
||||||
their value directly.
|
Variables of style *python* can be hooked to Python functions using
|
||||||
|
Python code you provide, so that the variable gets its value from the
|
||||||
|
evaluation of the Python code. Variables of style *internal* are used
|
||||||
|
by a few commands which set their value directly.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -166,15 +174,16 @@ simulation.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
When an input script line is encountered that defines a variable
|
When an input script line is encountered that defines a variable of
|
||||||
of style *equal* or *vector* or *atom* or *python* that contains a
|
style *equal* or *vector* or *atom* or *python* that contains a
|
||||||
formula or Python code, the formula is NOT immediately evaluated. It
|
formula or links to Python code, the formula or Python code is NOT
|
||||||
will be evaluated every time when the variable is **used** instead. If
|
immediately evaluated. Instead, it is evaluated each time the
|
||||||
you simply want to evaluate a formula in place you can use as
|
variable is **used**. If you simply want to evaluate a formula in
|
||||||
so-called. See the section below about "Immediate Evaluation of
|
place you can use a so-called immediate variable. as described in
|
||||||
Variables" for more details on the topic. This is also true of a
|
the preceding note. Or see the section below about "Immediate
|
||||||
*format* style variable since it evaluates another variable when it is
|
Evaluation of Variables" for more details on the topic. This is
|
||||||
invoked.
|
also true of a *format* style variable since it evaluates another
|
||||||
|
variable when it is invoked.
|
||||||
|
|
||||||
Variables of style *equal* and *vector* and *atom* can be used as
|
Variables of style *equal* and *vector* and *atom* can be used as
|
||||||
inputs to various other commands which evaluate their formulas as
|
inputs to various other commands which evaluate their formulas as
|
||||||
@ -183,12 +192,12 @@ this context, variables of style *timer* or *internal* or *python* can
|
|||||||
be used in place of an equal-style variable, with the following two
|
be used in place of an equal-style variable, with the following two
|
||||||
caveats.
|
caveats.
|
||||||
|
|
||||||
First, internal-style variables can be used except by commands that
|
First, internal-style variables require their values be set by code
|
||||||
set the value stored by the internal variable. When the LAMMPS
|
elsewhere in LAMMPS. When a LAMMPS input script or command evaluates
|
||||||
command evaluates the internal-style variable, it will use the value
|
an internal-style variable, it must have a current value set
|
||||||
set (internally) by another command. Second, python-style variables
|
(internally) via that mechanism. Second, python-style variables can
|
||||||
can be used so long as the associated Python function, as defined by
|
be used so long as the associated Python function, as defined by the
|
||||||
the :doc:`python <python>` command, returns a numeric value. When the
|
:doc:`python <python>` command, returns a numeric value. When the
|
||||||
LAMMPS command evaluates the python-style variable, the Python
|
LAMMPS command evaluates the python-style variable, the Python
|
||||||
function will be executed.
|
function will be executed.
|
||||||
|
|
||||||
@ -388,13 +397,24 @@ using the :doc:`command-line switch -var <Run_options>`.
|
|||||||
|
|
||||||
For the *internal* style a numeric value is provided. This value will
|
For the *internal* style a numeric value is provided. This value will
|
||||||
be assigned to the variable until a LAMMPS command sets it to a new
|
be assigned to the variable until a LAMMPS command sets it to a new
|
||||||
value. There are currently only two LAMMPS commands that require
|
value.
|
||||||
*internal* variables as inputs, because they reset them:
|
|
||||||
:doc:`create_atoms <create_atoms>` and :doc:`fix controller
|
Note however, that most commands which use internal-style variables do
|
||||||
<fix_controller>`. As mentioned above, an internal-style variable can
|
not require them to be defined in the input script. They create one or
|
||||||
be used in place of an equal-style variable anywhere else in an input
|
more internal-style variables if they do not already exist. Examples
|
||||||
script, e.g. as an argument to another command that allows for
|
are these commands:
|
||||||
equal-style variables.
|
|
||||||
|
* :doc:`create_atoms <create_atoms>`
|
||||||
|
* :doc:`fix deposit <fix_deposit>`
|
||||||
|
* :doc:`compute bond/local <compute_bond_local>`
|
||||||
|
* :doc:`compute angle/local <compute_angle_local>`
|
||||||
|
* :doc:`compute dihedral/local <compute_dihedral_local>`
|
||||||
|
* :doc:`python <python>` command in conjunction with Python function wrappers used in equal- and atom-style variable formulas
|
||||||
|
|
||||||
|
A command which does require an internal-style variable to be defined in
|
||||||
|
the input script is the :doc:`fix controller <fix_controller>` command,
|
||||||
|
because another (arbitrary) command typically also references the
|
||||||
|
variable.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -439,6 +459,15 @@ python-style variable can be used in place of an equal-style variable
|
|||||||
anywhere in an input script, e.g. as an argument to another command
|
anywhere in an input script, e.g. as an argument to another command
|
||||||
that allows for equal-style variables.
|
that allows for equal-style variables.
|
||||||
|
|
||||||
|
A python-style variable can also be used within the formula for an
|
||||||
|
equal-style or atom-style formula in a Python function wrapper, as
|
||||||
|
explained below for variable formulas. In this context, the usage
|
||||||
|
syntax is py_varname(arg1,arg2,...), where varname is the name of the
|
||||||
|
python-style variable. When a Python wrapper function is used in an
|
||||||
|
atom-style formula, it can be invoked once per atom using arguments
|
||||||
|
specific to each atom. The resulting values in the atom-style
|
||||||
|
variable can thus be calculated by Python code.
|
||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
For the *string* style, a single string is assigned to the variable.
|
For the *string* style, a single string is assigned to the variable.
|
||||||
@ -528,9 +557,9 @@ is a valid (though strange) variable formula:
|
|||||||
|
|
||||||
Specifically, a formula can contain numbers, constants, thermo
|
Specifically, a formula can contain numbers, constants, thermo
|
||||||
keywords, math operators, math functions, group functions, region
|
keywords, math operators, math functions, group functions, region
|
||||||
functions, special functions, feature functions, atom values, atom
|
functions, special functions, feature functions, Python function
|
||||||
vectors, custom atom properties, compute references, fix references, and references to other
|
wrappers, atom values, atom vectors, custom atom properties, compute
|
||||||
variables.
|
references, fix references, and references to other variables.
|
||||||
|
|
||||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| Number | 0.2, 100, 1.0e20, -15.4, etc |
|
| Number | 0.2, 100, 1.0e20, -15.4, etc |
|
||||||
@ -551,6 +580,8 @@ variables.
|
|||||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| Feature functions | is_available(category,feature), is_active(category,feature), is_defined(category,id) |
|
| Feature functions | is_available(category,feature), is_active(category,feature), is_defined(category,id) |
|
||||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| Python func wrapper | py_varname(x,y,z,...) |
|
||||||
|
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| Atom values | id[i], mass[i], type[i], mol[i], x[i], y[i], z[i], vx[i], vy[i], vz[i], fx[i], fy[i], fz[i], q[i] |
|
| Atom values | id[i], mass[i], type[i], mol[i], x[i], y[i], z[i], vx[i], vy[i], vz[i], fx[i], fy[i], fz[i], q[i] |
|
||||||
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
| Atom vectors | id, mass, type, mol, x, y, z, vx, vy, vz, fx, fy, fz, q |
|
| Atom vectors | id, mass, type, mol, x, y, z, vx, vy, vz, fx, fy, fz, q |
|
||||||
@ -1161,6 +1192,84 @@ variable name.
|
|||||||
|
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
Python Function wrapper
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
A Python function wrapper enables the formula for an equal-style or
|
||||||
|
atom-style variable to invoke functions coded in Python. In the case
|
||||||
|
of an equal-style variable, the Python-coded function will be invoked
|
||||||
|
once. In the case of an atom-style variable, it can be invoked once
|
||||||
|
per atom, if one or more of its arguments include a per-atom quantity,
|
||||||
|
e.g. the position of an atom. As illustrated below, the reason to use
|
||||||
|
a Python function wrapper is to make it easy to pass LAMMPS-related
|
||||||
|
arguments to the Python-coded function associated with a python-style
|
||||||
|
variable.
|
||||||
|
|
||||||
|
The syntax for defining a Python function wrapper is
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
py_varname(arg1,arg2,...argN)
|
||||||
|
|
||||||
|
where *varname* is the name of a python-style variable which couples
|
||||||
|
to a Python-coded function. The function will be passed the zero or
|
||||||
|
more arguments listed in parentheses: *arg1*, *arg2*, ... *argN*. As
|
||||||
|
with Math Functions, each argument can itself be an arbitrarily
|
||||||
|
complex formula.
|
||||||
|
|
||||||
|
A Python function wrapper can be used in the following manner by an
|
||||||
|
input script:
|
||||||
|
|
||||||
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
|
variable foo python truncate
|
||||||
|
python truncate return v_foo input 1 v_arg format fi here """
|
||||||
|
def truncate(x):
|
||||||
|
return int(x)
|
||||||
|
"""
|
||||||
|
variable xtrunc atom py_foo(x)
|
||||||
|
variable ytrunc atom py_foo(y)
|
||||||
|
variable ztrunc atom py_foo(z)
|
||||||
|
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
|
||||||
|
The first two commands define a python-style variable *foo* and couple
|
||||||
|
it to the Python-coded function *truncate()* which takes a single
|
||||||
|
floating point argument, and returns its truncated integer value. In
|
||||||
|
this case, the Python code for truncate() is included in the *python*
|
||||||
|
command; it could also be contained in a file. See the :doc:`python
|
||||||
|
<python>` command doc page for details.
|
||||||
|
|
||||||
|
The next three commands define atom-style variables *xtrunc*,
|
||||||
|
*ytrunc*, and *ztrunc*. Each of them include the same Python function
|
||||||
|
wrapper in their formula, with a different argument. The atom-style
|
||||||
|
variable *xtrunc* will invoke the python-style variable *foo*, which
|
||||||
|
will in turn invoke the Python-coded *truncate()* method. Because
|
||||||
|
*xtrunc* is an atom-style variable, and the argument *x* in the Python
|
||||||
|
function wrapper is a per-atom quantity (the x-coord of each atom),
|
||||||
|
each processor will invoke the *truncate()* method once per atom, for
|
||||||
|
the atoms it owns.
|
||||||
|
|
||||||
|
When invoked for the Ith atom, the value of the *arg* internal-style
|
||||||
|
variable, defined by the *python* command, is set to the x-coord of
|
||||||
|
the Ith atom. The call via python-style variable *foo* to the Python
|
||||||
|
*truncate()* function passes the value of the *arg* variable as its
|
||||||
|
first (and only) argument. Likewise, the return value of the Python
|
||||||
|
function becomes is stored by the python-style variable *foo* and used
|
||||||
|
in the *xtrunc* atom-style variable formula for the Ith atom.
|
||||||
|
|
||||||
|
The resulting per-atom vector for *xtrunc* will thus contain the
|
||||||
|
truncated x-coord of every atom in the system. The dump command
|
||||||
|
includes the truncated xyz coords for each atom in its output.
|
||||||
|
|
||||||
|
See the :doc:`python <python>` command for more details on options the
|
||||||
|
*python* command can specify as well as examples of more complex Python
|
||||||
|
functions which can be wrapped in this manner. In particular, the
|
||||||
|
Python function can take a variety of arguments, some generated by the
|
||||||
|
*python* command, and others by the arguments of the Python function
|
||||||
|
wrapper.
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
Atom Values and Vectors
|
Atom Values and Vectors
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
@ -3129,6 +3129,7 @@ Pxy
|
|||||||
pxz
|
pxz
|
||||||
py
|
py
|
||||||
Py
|
Py
|
||||||
|
pyargs
|
||||||
pydir
|
pydir
|
||||||
pylammps
|
pylammps
|
||||||
PyLammps
|
PyLammps
|
||||||
@ -4080,6 +4081,7 @@ Vanduyfhuys
|
|||||||
varargs
|
varargs
|
||||||
varavg
|
varavg
|
||||||
variational
|
variational
|
||||||
|
varname
|
||||||
Varshalovich
|
Varshalovich
|
||||||
Varshney
|
Varshney
|
||||||
vashishta
|
vashishta
|
||||||
|
|||||||
234
examples/python/dump.1May25.python.wrap.g++.1
Normal file
234
examples/python/dump.1May25.python.wrap.g++.1
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
ITEM: TIMESTEP
|
||||||
|
0
|
||||||
|
ITEM: NUMBER OF ATOMS
|
||||||
|
108
|
||||||
|
ITEM: BOX BOUNDS pp pp pp
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
ITEM: ATOMS id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
1 0 0 0 0 0 0
|
||||||
|
2 0.839798 0.839798 0 0 0 0
|
||||||
|
3 0.839798 0 0.839798 0 0 0
|
||||||
|
4 0 0.839798 0.839798 0 0 0
|
||||||
|
5 1.6796 0 0 1 0 0
|
||||||
|
6 2.51939 0.839798 0 2 0 0
|
||||||
|
7 2.51939 0 0.839798 2 0 0
|
||||||
|
8 1.6796 0.839798 0.839798 1 0 0
|
||||||
|
9 3.35919 0 0 3 0 0
|
||||||
|
10 4.19899 0.839798 0 4 0 0
|
||||||
|
11 4.19899 0 0.839798 4 0 0
|
||||||
|
12 3.35919 0.839798 0.839798 3 0 0
|
||||||
|
13 0 1.6796 0 0 1 0
|
||||||
|
14 0.839798 2.51939 0 0 2 0
|
||||||
|
15 0.839798 1.6796 0.839798 0 1 0
|
||||||
|
16 0 2.51939 0.839798 0 2 0
|
||||||
|
17 1.6796 1.6796 0 1 1 0
|
||||||
|
18 2.51939 2.51939 0 2 2 0
|
||||||
|
19 2.51939 1.6796 0.839798 2 1 0
|
||||||
|
20 1.6796 2.51939 0.839798 1 2 0
|
||||||
|
21 3.35919 1.6796 0 3 1 0
|
||||||
|
22 4.19899 2.51939 0 4 2 0
|
||||||
|
23 4.19899 1.6796 0.839798 4 1 0
|
||||||
|
24 3.35919 2.51939 0.839798 3 2 0
|
||||||
|
25 0 3.35919 0 0 3 0
|
||||||
|
26 0.839798 4.19899 0 0 4 0
|
||||||
|
27 0.839798 3.35919 0.839798 0 3 0
|
||||||
|
28 0 4.19899 0.839798 0 4 0
|
||||||
|
29 1.6796 3.35919 0 1 3 0
|
||||||
|
30 2.51939 4.19899 0 2 4 0
|
||||||
|
31 2.51939 3.35919 0.839798 2 3 0
|
||||||
|
32 1.6796 4.19899 0.839798 1 4 0
|
||||||
|
33 3.35919 3.35919 0 3 3 0
|
||||||
|
34 4.19899 4.19899 0 4 4 0
|
||||||
|
35 4.19899 3.35919 0.839798 4 3 0
|
||||||
|
36 3.35919 4.19899 0.839798 3 4 0
|
||||||
|
37 0 0 1.6796 0 0 1
|
||||||
|
38 0.839798 0.839798 1.6796 0 0 1
|
||||||
|
39 0.839798 0 2.51939 0 0 2
|
||||||
|
40 0 0.839798 2.51939 0 0 2
|
||||||
|
41 1.6796 0 1.6796 1 0 1
|
||||||
|
42 2.51939 0.839798 1.6796 2 0 1
|
||||||
|
43 2.51939 0 2.51939 2 0 2
|
||||||
|
44 1.6796 0.839798 2.51939 1 0 2
|
||||||
|
45 3.35919 0 1.6796 3 0 1
|
||||||
|
46 4.19899 0.839798 1.6796 4 0 1
|
||||||
|
47 4.19899 0 2.51939 4 0 2
|
||||||
|
48 3.35919 0.839798 2.51939 3 0 2
|
||||||
|
49 0 1.6796 1.6796 0 1 1
|
||||||
|
50 0.839798 2.51939 1.6796 0 2 1
|
||||||
|
51 0.839798 1.6796 2.51939 0 1 2
|
||||||
|
52 0 2.51939 2.51939 0 2 2
|
||||||
|
53 1.6796 1.6796 1.6796 1 1 1
|
||||||
|
54 2.51939 2.51939 1.6796 2 2 1
|
||||||
|
55 2.51939 1.6796 2.51939 2 1 2
|
||||||
|
56 1.6796 2.51939 2.51939 1 2 2
|
||||||
|
57 3.35919 1.6796 1.6796 3 1 1
|
||||||
|
58 4.19899 2.51939 1.6796 4 2 1
|
||||||
|
59 4.19899 1.6796 2.51939 4 1 2
|
||||||
|
60 3.35919 2.51939 2.51939 3 2 2
|
||||||
|
61 0 3.35919 1.6796 0 3 1
|
||||||
|
62 0.839798 4.19899 1.6796 0 4 1
|
||||||
|
63 0.839798 3.35919 2.51939 0 3 2
|
||||||
|
64 0 4.19899 2.51939 0 4 2
|
||||||
|
65 1.6796 3.35919 1.6796 1 3 1
|
||||||
|
66 2.51939 4.19899 1.6796 2 4 1
|
||||||
|
67 2.51939 3.35919 2.51939 2 3 2
|
||||||
|
68 1.6796 4.19899 2.51939 1 4 2
|
||||||
|
69 3.35919 3.35919 1.6796 3 3 1
|
||||||
|
70 4.19899 4.19899 1.6796 4 4 1
|
||||||
|
71 4.19899 3.35919 2.51939 4 3 2
|
||||||
|
72 3.35919 4.19899 2.51939 3 4 2
|
||||||
|
73 0 0 3.35919 0 0 3
|
||||||
|
74 0.839798 0.839798 3.35919 0 0 3
|
||||||
|
75 0.839798 0 4.19899 0 0 4
|
||||||
|
76 0 0.839798 4.19899 0 0 4
|
||||||
|
77 1.6796 0 3.35919 1 0 3
|
||||||
|
78 2.51939 0.839798 3.35919 2 0 3
|
||||||
|
79 2.51939 0 4.19899 2 0 4
|
||||||
|
80 1.6796 0.839798 4.19899 1 0 4
|
||||||
|
81 3.35919 0 3.35919 3 0 3
|
||||||
|
82 4.19899 0.839798 3.35919 4 0 3
|
||||||
|
83 4.19899 0 4.19899 4 0 4
|
||||||
|
84 3.35919 0.839798 4.19899 3 0 4
|
||||||
|
85 0 1.6796 3.35919 0 1 3
|
||||||
|
86 0.839798 2.51939 3.35919 0 2 3
|
||||||
|
87 0.839798 1.6796 4.19899 0 1 4
|
||||||
|
88 0 2.51939 4.19899 0 2 4
|
||||||
|
89 1.6796 1.6796 3.35919 1 1 3
|
||||||
|
90 2.51939 2.51939 3.35919 2 2 3
|
||||||
|
91 2.51939 1.6796 4.19899 2 1 4
|
||||||
|
92 1.6796 2.51939 4.19899 1 2 4
|
||||||
|
93 3.35919 1.6796 3.35919 3 1 3
|
||||||
|
94 4.19899 2.51939 3.35919 4 2 3
|
||||||
|
95 4.19899 1.6796 4.19899 4 1 4
|
||||||
|
96 3.35919 2.51939 4.19899 3 2 4
|
||||||
|
97 0 3.35919 3.35919 0 3 3
|
||||||
|
98 0.839798 4.19899 3.35919 0 4 3
|
||||||
|
99 0.839798 3.35919 4.19899 0 3 4
|
||||||
|
100 0 4.19899 4.19899 0 4 4
|
||||||
|
101 1.6796 3.35919 3.35919 1 3 3
|
||||||
|
102 2.51939 4.19899 3.35919 2 4 3
|
||||||
|
103 2.51939 3.35919 4.19899 2 3 4
|
||||||
|
104 1.6796 4.19899 4.19899 1 4 4
|
||||||
|
105 3.35919 3.35919 3.35919 3 3 3
|
||||||
|
106 4.19899 4.19899 3.35919 4 4 3
|
||||||
|
107 4.19899 3.35919 4.19899 4 3 4
|
||||||
|
108 3.35919 4.19899 4.19899 3 4 4
|
||||||
|
ITEM: TIMESTEP
|
||||||
|
100
|
||||||
|
ITEM: NUMBER OF ATOMS
|
||||||
|
108
|
||||||
|
ITEM: BOX BOUNDS pp pp pp
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
ITEM: ATOMS id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
1 4.97801 0.0605812 4.88474 4 0 4
|
||||||
|
2 0.800305 0.813213 0.0576603 0 0 0
|
||||||
|
3 0.6485 5.00484 0.836947 0 5 0
|
||||||
|
4 5.01236 0.786108 0.77507 5 0 0
|
||||||
|
5 1.50261 4.9277 4.9755 1 4 4
|
||||||
|
6 2.46756 0.653742 5.0003 2 0 5
|
||||||
|
7 2.55699 4.96491 0.926671 2 4 0
|
||||||
|
8 1.62464 0.676882 0.777822 1 0 0
|
||||||
|
9 3.57018 0.00324557 4.76943 3 0 4
|
||||||
|
10 4.24909 0.985667 5.01613 4 0 5
|
||||||
|
11 4.13124 0.178555 0.700886 4 0 0
|
||||||
|
12 3.22537 0.963341 0.639686 3 0 0
|
||||||
|
13 4.90815 1.75715 0.0826318 4 1 0
|
||||||
|
14 1.00239 2.45421 0.0111309 1 2 0
|
||||||
|
15 0.88902 1.62097 0.874547 0 1 0
|
||||||
|
16 0.269512 2.41383 0.844638 0 2 0
|
||||||
|
17 1.54513 1.51174 0.0869798 1 1 0
|
||||||
|
18 2.0637 2.5991 0.0826392 2 2 0
|
||||||
|
19 2.44634 1.71869 0.918144 2 1 0
|
||||||
|
20 1.57997 2.52559 1.04361 1 2 1
|
||||||
|
21 3.26063 2.10027 0.0160498 3 2 0
|
||||||
|
22 4.21774 2.61172 0.0367453 4 2 0
|
||||||
|
23 4.32215 1.8333 0.925663 4 1 0
|
||||||
|
24 3.38151 2.6788 0.906258 3 2 0
|
||||||
|
25 0.275459 3.26838 0.21932 0 3 0
|
||||||
|
26 0.675354 4.14887 4.94054 0 4 4
|
||||||
|
27 0.867201 3.35405 1.17655 0 3 1
|
||||||
|
28 4.78788 4.34273 0.478103 4 4 0
|
||||||
|
29 1.42014 3.50181 0.191388 1 3 0
|
||||||
|
30 2.39935 4.14279 0.0726977 2 4 0
|
||||||
|
31 2.68157 3.57418 0.921633 2 3 0
|
||||||
|
32 1.77965 4.13041 0.925765 1 4 0
|
||||||
|
33 3.10555 3.22911 5.00703 3 3 5
|
||||||
|
34 4.24908 3.67507 4.83053 4 3 4
|
||||||
|
35 4.2444 3.59428 0.837193 4 3 0
|
||||||
|
36 3.52155 4.21032 0.423884 3 4 0
|
||||||
|
37 0.00881412 4.90616 1.74242 0 4 1
|
||||||
|
38 0.800033 0.812556 1.72553 0 0 1
|
||||||
|
39 0.929754 0.0251285 2.53734 0 0 2
|
||||||
|
40 0.0189933 0.897729 2.4272 0 0 2
|
||||||
|
41 1.77025 0.0864618 1.69637 1 0 1
|
||||||
|
42 2.6077 0.984882 1.7897 2 0 1
|
||||||
|
43 2.55819 4.95626 2.45373 2 4 2
|
||||||
|
44 1.77963 0.875522 2.5056 1 0 2
|
||||||
|
45 3.50499 0.0189748 1.5186 3 0 1
|
||||||
|
46 4.47856 0.849521 1.59138 4 0 1
|
||||||
|
47 3.99 0.309367 2.42507 3 0 2
|
||||||
|
48 3.06373 0.748905 2.87477 3 0 2
|
||||||
|
49 0.149175 1.72252 1.81302 0 1 1
|
||||||
|
50 0.963279 2.42412 1.76899 0 2 1
|
||||||
|
51 0.879984 1.74899 2.55389 0 1 2
|
||||||
|
52 0.211736 2.57456 2.48446 0 2 2
|
||||||
|
53 1.75238 1.7433 1.79028 1 1 1
|
||||||
|
54 2.61023 2.6802 1.55816 2 2 1
|
||||||
|
55 2.55259 1.72904 2.60295 2 1 2
|
||||||
|
56 1.7903 2.56204 2.41895 1 2 2
|
||||||
|
57 3.43857 1.71819 1.54054 3 1 1
|
||||||
|
58 4.20455 2.5331 1.87607 4 2 1
|
||||||
|
59 4.12961 1.48438 2.40107 4 1 2
|
||||||
|
60 3.36606 2.52455 2.67203 3 2 2
|
||||||
|
61 0.0138563 3.23504 1.76147 0 3 1
|
||||||
|
62 0.968224 4.42746 1.67526 0 4 1
|
||||||
|
63 0.965745 3.43479 2.52674 0 3 2
|
||||||
|
64 0.144542 4.27264 2.61793 0 4 2
|
||||||
|
65 1.7741 3.32184 1.66819 1 3 1
|
||||||
|
66 2.4878 4.29352 1.69069 2 4 1
|
||||||
|
67 2.56992 3.44579 2.4534 2 3 2
|
||||||
|
68 1.72356 4.2344 2.49376 1 4 2
|
||||||
|
69 3.43363 3.36417 1.87451 3 3 1
|
||||||
|
70 4.32623 4.1046 1.69102 4 4 1
|
||||||
|
71 4.22927 3.23505 2.64208 4 3 2
|
||||||
|
72 3.41086 4.28362 2.42553 3 4 2
|
||||||
|
73 4.85349 0.0953155 3.14546 4 0 3
|
||||||
|
74 0.833593 0.840282 3.27238 0 0 3
|
||||||
|
75 0.578712 4.99093 3.85234 0 4 3
|
||||||
|
76 0.119704 1.00404 4.09942 0 1 4
|
||||||
|
77 1.78347 4.95586 3.31184 1 4 3
|
||||||
|
78 2.34318 0.736887 3.54475 2 0 3
|
||||||
|
79 2.34858 4.82316 4.28272 2 4 4
|
||||||
|
80 1.55893 0.765128 4.31112 1 0 4
|
||||||
|
81 3.13128 0.0257347 3.70936 3 0 3
|
||||||
|
82 4.10851 0.877375 3.36388 4 0 3
|
||||||
|
83 4.30691 4.69041 4.14081 4 4 4
|
||||||
|
84 3.48471 1.07347 4.35888 3 1 4
|
||||||
|
85 0.0668209 1.77975 3.29313 0 1 3
|
||||||
|
86 0.894798 2.5043 3.34172 0 2 3
|
||||||
|
87 0.743432 1.71961 4.3483 0 1 4
|
||||||
|
88 0.135168 2.69084 4.12098 0 2 4
|
||||||
|
89 1.73749 1.5259 3.46692 1 1 3
|
||||||
|
90 2.47391 2.57508 3.27574 2 2 3
|
||||||
|
91 2.4825 1.46064 4.38907 2 1 4
|
||||||
|
92 1.67786 2.47309 4.03082 1 2 4
|
||||||
|
93 3.34694 1.70248 3.44784 3 1 3
|
||||||
|
94 4.20676 2.29697 3.23228 4 2 3
|
||||||
|
95 4.31748 1.76411 4.20898 4 1 4
|
||||||
|
96 3.1135 2.59262 4.08996 3 2 4
|
||||||
|
97 0.0727406 3.44797 3.30247 0 3 3
|
||||||
|
98 1.0752 4.05296 3.38036 1 4 3
|
||||||
|
99 1.0085 3.35058 4.3598 1 3 4
|
||||||
|
100 0.054939 4.00087 4.11831 0 4 4
|
||||||
|
101 1.72259 3.24691 3.19685 1 3 3
|
||||||
|
102 2.54324 4.21582 3.29642 2 4 3
|
||||||
|
103 2.33008 3.38603 4.27885 2 3 4
|
||||||
|
104 1.65617 4.10852 4.3491 1 4 4
|
||||||
|
105 3.14646 3.43756 3.28105 3 3 3
|
||||||
|
106 4.09781 4.10691 3.24439 4 4 3
|
||||||
|
107 4.1529 3.22538 3.79605 4 3 3
|
||||||
|
108 3.16394 3.96553 4.31023 3 3 4
|
||||||
234
examples/python/dump.1May25.python.wrap.g++.4
Normal file
234
examples/python/dump.1May25.python.wrap.g++.4
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
ITEM: TIMESTEP
|
||||||
|
0
|
||||||
|
ITEM: NUMBER OF ATOMS
|
||||||
|
108
|
||||||
|
ITEM: BOX BOUNDS pp pp pp
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
ITEM: ATOMS id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
1 0 0 0 0 0 0
|
||||||
|
2 0.839798 0.839798 0 0 0 0
|
||||||
|
3 0.839798 0 0.839798 0 0 0
|
||||||
|
4 0 0.839798 0.839798 0 0 0
|
||||||
|
13 0 1.6796 0 0 1 0
|
||||||
|
14 0.839798 1.6796 0.839798 0 1 0
|
||||||
|
19 0 0 1.6796 0 0 1
|
||||||
|
20 0.839798 0.839798 1.6796 0 0 1
|
||||||
|
25 0 1.6796 1.6796 0 1 1
|
||||||
|
5 1.6796 0 0 1 0 0
|
||||||
|
6 2.51939 0.839798 0 2 0 0
|
||||||
|
7 2.51939 0 0.839798 2 0 0
|
||||||
|
8 1.6796 0.839798 0.839798 1 0 0
|
||||||
|
15 1.6796 1.6796 0 1 1 0
|
||||||
|
16 2.51939 1.6796 0.839798 2 1 0
|
||||||
|
21 1.6796 0 1.6796 1 0 1
|
||||||
|
22 2.51939 0.839798 1.6796 2 0 1
|
||||||
|
26 1.6796 1.6796 1.6796 1 1 1
|
||||||
|
9 3.35919 0 0 3 0 0
|
||||||
|
10 4.19899 0.839798 0 4 0 0
|
||||||
|
11 4.19899 0 0.839798 4 0 0
|
||||||
|
12 3.35919 0.839798 0.839798 3 0 0
|
||||||
|
17 3.35919 1.6796 0 3 1 0
|
||||||
|
18 4.19899 1.6796 0.839798 4 1 0
|
||||||
|
23 3.35919 0 1.6796 3 0 1
|
||||||
|
24 4.19899 0.839798 1.6796 4 0 1
|
||||||
|
27 3.35919 1.6796 1.6796 3 1 1
|
||||||
|
28 0.839798 0 2.51939 0 0 2
|
||||||
|
29 0 0.839798 2.51939 0 0 2
|
||||||
|
34 0.839798 1.6796 2.51939 0 1 2
|
||||||
|
37 0 0 3.35919 0 0 3
|
||||||
|
38 0.839798 0.839798 3.35919 0 0 3
|
||||||
|
39 0.839798 0 4.19899 0 0 4
|
||||||
|
40 0 0.839798 4.19899 0 0 4
|
||||||
|
49 0 1.6796 3.35919 0 1 3
|
||||||
|
50 0.839798 1.6796 4.19899 0 1 4
|
||||||
|
30 2.51939 0 2.51939 2 0 2
|
||||||
|
31 1.6796 0.839798 2.51939 1 0 2
|
||||||
|
35 2.51939 1.6796 2.51939 2 1 2
|
||||||
|
41 1.6796 0 3.35919 1 0 3
|
||||||
|
42 2.51939 0.839798 3.35919 2 0 3
|
||||||
|
43 2.51939 0 4.19899 2 0 4
|
||||||
|
44 1.6796 0.839798 4.19899 1 0 4
|
||||||
|
51 1.6796 1.6796 3.35919 1 1 3
|
||||||
|
52 2.51939 1.6796 4.19899 2 1 4
|
||||||
|
32 4.19899 0 2.51939 4 0 2
|
||||||
|
33 3.35919 0.839798 2.51939 3 0 2
|
||||||
|
36 4.19899 1.6796 2.51939 4 1 2
|
||||||
|
45 3.35919 0 3.35919 3 0 3
|
||||||
|
46 4.19899 0.839798 3.35919 4 0 3
|
||||||
|
47 4.19899 0 4.19899 4 0 4
|
||||||
|
48 3.35919 0.839798 4.19899 3 0 4
|
||||||
|
53 3.35919 1.6796 3.35919 3 1 3
|
||||||
|
54 4.19899 1.6796 4.19899 4 1 4
|
||||||
|
55 0.839798 2.51939 0 0 2 0
|
||||||
|
56 0 2.51939 0.839798 0 2 0
|
||||||
|
61 0 3.35919 0 0 3 0
|
||||||
|
62 0.839798 4.19899 0 0 4 0
|
||||||
|
63 0.839798 3.35919 0.839798 0 3 0
|
||||||
|
64 0 4.19899 0.839798 0 4 0
|
||||||
|
73 0.839798 2.51939 1.6796 0 2 1
|
||||||
|
76 0 3.35919 1.6796 0 3 1
|
||||||
|
77 0.839798 4.19899 1.6796 0 4 1
|
||||||
|
57 2.51939 2.51939 0 2 2 0
|
||||||
|
58 1.6796 2.51939 0.839798 1 2 0
|
||||||
|
65 1.6796 3.35919 0 1 3 0
|
||||||
|
66 2.51939 4.19899 0 2 4 0
|
||||||
|
67 2.51939 3.35919 0.839798 2 3 0
|
||||||
|
68 1.6796 4.19899 0.839798 1 4 0
|
||||||
|
74 2.51939 2.51939 1.6796 2 2 1
|
||||||
|
78 1.6796 3.35919 1.6796 1 3 1
|
||||||
|
79 2.51939 4.19899 1.6796 2 4 1
|
||||||
|
59 4.19899 2.51939 0 4 2 0
|
||||||
|
60 3.35919 2.51939 0.839798 3 2 0
|
||||||
|
69 3.35919 3.35919 0 3 3 0
|
||||||
|
70 4.19899 4.19899 0 4 4 0
|
||||||
|
71 4.19899 3.35919 0.839798 4 3 0
|
||||||
|
72 3.35919 4.19899 0.839798 3 4 0
|
||||||
|
75 4.19899 2.51939 1.6796 4 2 1
|
||||||
|
80 3.35919 3.35919 1.6796 3 3 1
|
||||||
|
81 4.19899 4.19899 1.6796 4 4 1
|
||||||
|
82 0 2.51939 2.51939 0 2 2
|
||||||
|
85 0.839798 3.35919 2.51939 0 3 2
|
||||||
|
86 0 4.19899 2.51939 0 4 2
|
||||||
|
91 0.839798 2.51939 3.35919 0 2 3
|
||||||
|
92 0 2.51939 4.19899 0 2 4
|
||||||
|
97 0 3.35919 3.35919 0 3 3
|
||||||
|
98 0.839798 4.19899 3.35919 0 4 3
|
||||||
|
99 0.839798 3.35919 4.19899 0 3 4
|
||||||
|
100 0 4.19899 4.19899 0 4 4
|
||||||
|
83 1.6796 2.51939 2.51939 1 2 2
|
||||||
|
87 2.51939 3.35919 2.51939 2 3 2
|
||||||
|
88 1.6796 4.19899 2.51939 1 4 2
|
||||||
|
93 2.51939 2.51939 3.35919 2 2 3
|
||||||
|
94 1.6796 2.51939 4.19899 1 2 4
|
||||||
|
101 1.6796 3.35919 3.35919 1 3 3
|
||||||
|
102 2.51939 4.19899 3.35919 2 4 3
|
||||||
|
103 2.51939 3.35919 4.19899 2 3 4
|
||||||
|
104 1.6796 4.19899 4.19899 1 4 4
|
||||||
|
84 3.35919 2.51939 2.51939 3 2 2
|
||||||
|
89 4.19899 3.35919 2.51939 4 3 2
|
||||||
|
90 3.35919 4.19899 2.51939 3 4 2
|
||||||
|
95 4.19899 2.51939 3.35919 4 2 3
|
||||||
|
96 3.35919 2.51939 4.19899 3 2 4
|
||||||
|
105 3.35919 3.35919 3.35919 3 3 3
|
||||||
|
106 4.19899 4.19899 3.35919 4 4 3
|
||||||
|
107 4.19899 3.35919 4.19899 4 3 4
|
||||||
|
108 3.35919 4.19899 4.19899 3 4 4
|
||||||
|
ITEM: TIMESTEP
|
||||||
|
100
|
||||||
|
ITEM: NUMBER OF ATOMS
|
||||||
|
108
|
||||||
|
ITEM: BOX BOUNDS pp pp pp
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
0.0000000000000000e+00 5.0387885741475218e+00
|
||||||
|
ITEM: ATOMS id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
27 3.43857 1.71819 1.54054 3 1 1
|
||||||
|
55 1.00239 2.45421 0.0111309 1 2 0
|
||||||
|
24 4.47856 0.849521 1.59138 4 0 1
|
||||||
|
4 5.01236 0.786108 0.77507 5 0 0
|
||||||
|
13 4.90815 1.75715 0.0826318 4 1 0
|
||||||
|
14 0.88902 1.62097 0.874547 0 1 0
|
||||||
|
23 3.50499 0.0189748 1.5186 3 0 1
|
||||||
|
20 0.800033 0.812556 1.72553 0 0 1
|
||||||
|
25 0.149175 1.72252 1.81302 0 1 1
|
||||||
|
18 4.32215 1.8333 0.925663 4 1 0
|
||||||
|
2 0.800305 0.813213 0.0576603 0 0 0
|
||||||
|
11 4.13124 0.178555 0.700886 4 0 0
|
||||||
|
8 1.62464 0.676882 0.777822 1 0 0
|
||||||
|
15 1.54513 1.51174 0.0869798 1 1 0
|
||||||
|
16 2.44634 1.71869 0.918144 2 1 0
|
||||||
|
21 1.77025 0.0864618 1.69637 1 0 1
|
||||||
|
22 2.6077 0.984882 1.7897 2 0 1
|
||||||
|
26 1.75238 1.7433 1.79028 1 1 1
|
||||||
|
56 0.269512 2.41383 0.844638 0 2 0
|
||||||
|
73 0.963279 2.42412 1.76899 0 2 1
|
||||||
|
12 3.22537 0.963341 0.639686 3 0 0
|
||||||
|
29 0.0189933 0.897729 2.4272 0 0 2
|
||||||
|
36 4.12961 1.48438 2.40107 4 1 2
|
||||||
|
31 1.77963 0.875522 2.5056 1 0 2
|
||||||
|
17 3.26063 2.10027 0.0160498 3 2 0
|
||||||
|
32 3.99 0.309367 2.42507 3 0 2
|
||||||
|
10 4.24909 0.985667 5.01613 4 0 5
|
||||||
|
9 3.57018 0.00324557 4.76943 3 0 4
|
||||||
|
34 0.879984 1.74899 2.55389 0 1 2
|
||||||
|
54 4.31748 1.76411 4.20898 4 1 4
|
||||||
|
38 0.833593 0.840282 3.27238 0 0 3
|
||||||
|
53 3.34694 1.70248 3.44784 3 1 3
|
||||||
|
40 0.119704 1.00404 4.09942 0 1 4
|
||||||
|
49 0.0668209 1.77975 3.29313 0 1 3
|
||||||
|
50 0.743432 1.71961 4.3483 0 1 4
|
||||||
|
1 4.97801 0.0605812 4.88474 4 0 4
|
||||||
|
28 0.929754 0.0251285 2.53734 0 0 2
|
||||||
|
94 1.67786 2.47309 4.03082 1 2 4
|
||||||
|
48 3.48471 1.07347 4.35888 3 1 4
|
||||||
|
42 2.34318 0.736887 3.54475 2 0 3
|
||||||
|
46 4.10851 0.877375 3.36388 4 0 3
|
||||||
|
44 1.55893 0.765128 4.31112 1 0 4
|
||||||
|
51 1.73749 1.5259 3.46692 1 1 3
|
||||||
|
52 2.4825 1.46064 4.38907 2 1 4
|
||||||
|
45 3.13128 0.0257347 3.70936 3 0 3
|
||||||
|
33 3.06373 0.748905 2.87477 3 0 2
|
||||||
|
37 4.85349 0.0953155 3.14546 4 0 3
|
||||||
|
95 4.20676 2.29697 3.23228 4 2 3
|
||||||
|
91 0.894798 2.5043 3.34172 0 2 3
|
||||||
|
6 2.46756 0.653742 5.0003 2 0 5
|
||||||
|
35 2.55259 1.72904 2.60295 2 1 2
|
||||||
|
75 4.20455 2.5331 1.87607 4 2 1
|
||||||
|
83 1.7903 2.56204 2.41895 1 2 2
|
||||||
|
90 3.41086 4.28362 2.42553 3 4 2
|
||||||
|
7 2.55699 4.96491 0.926671 2 4 0
|
||||||
|
63 0.867201 3.35405 1.17655 0 3 1
|
||||||
|
64 4.78788 4.34273 0.478103 4 4 0
|
||||||
|
81 4.32623 4.1046 1.69102 4 4 1
|
||||||
|
76 0.0138563 3.23504 1.76147 0 3 1
|
||||||
|
77 0.968224 4.42746 1.67526 0 4 1
|
||||||
|
57 2.0637 2.5991 0.0826392 2 2 0
|
||||||
|
80 3.43363 3.36417 1.87451 3 3 1
|
||||||
|
65 1.42014 3.50181 0.191388 1 3 0
|
||||||
|
58 1.57997 2.52559 1.04361 1 2 1
|
||||||
|
67 2.68157 3.57418 0.921633 2 3 0
|
||||||
|
68 1.77965 4.13041 0.925765 1 4 0
|
||||||
|
74 2.61023 2.6802 1.55816 2 2 1
|
||||||
|
78 1.7741 3.32184 1.66819 1 3 1
|
||||||
|
79 2.4878 4.29352 1.69069 2 4 1
|
||||||
|
59 4.21774 2.61172 0.0367453 4 2 0
|
||||||
|
72 3.52155 4.21032 0.423884 3 4 0
|
||||||
|
19 0.00881412 4.90616 1.74242 0 4 1
|
||||||
|
71 4.2444 3.59428 0.837193 4 3 0
|
||||||
|
60 3.38151 2.6788 0.906258 3 2 0
|
||||||
|
88 1.72356 4.2344 2.49376 1 4 2
|
||||||
|
87 2.56992 3.44579 2.4534 2 3 2
|
||||||
|
61 0.275459 3.26838 0.21932 0 3 0
|
||||||
|
3 0.6485 5.00484 0.836947 0 5 0
|
||||||
|
66 2.39935 4.14279 0.0726977 2 4 0
|
||||||
|
82 0.211736 2.57456 2.48446 0 2 2
|
||||||
|
30 2.55819 4.95626 2.45373 2 4 2
|
||||||
|
108 3.16394 3.96553 4.31023 3 3 4
|
||||||
|
62 0.675354 4.14887 4.94054 0 4 4
|
||||||
|
47 4.30691 4.69041 4.14081 4 4 4
|
||||||
|
107 4.1529 3.22538 3.79605 4 3 3
|
||||||
|
92 0.135168 2.69084 4.12098 0 2 4
|
||||||
|
97 0.0727406 3.44797 3.30247 0 3 3
|
||||||
|
98 1.0752 4.05296 3.38036 1 4 3
|
||||||
|
99 1.0085 3.35058 4.3598 1 3 4
|
||||||
|
100 0.054939 4.00087 4.11831 0 4 4
|
||||||
|
106 4.09781 4.10691 3.24439 4 4 3
|
||||||
|
70 4.24908 3.67507 4.83053 4 3 4
|
||||||
|
43 2.34858 4.82316 4.28272 2 4 4
|
||||||
|
105 3.14646 3.43756 3.28105 3 3 3
|
||||||
|
96 3.1135 2.59262 4.08996 3 2 4
|
||||||
|
101 1.72259 3.24691 3.19685 1 3 3
|
||||||
|
102 2.54324 4.21582 3.29642 2 4 3
|
||||||
|
103 2.33008 3.38603 4.27885 2 3 4
|
||||||
|
104 1.65617 4.10852 4.3491 1 4 4
|
||||||
|
84 3.36606 2.52455 2.67203 3 2 2
|
||||||
|
89 4.22927 3.23505 2.64208 4 3 2
|
||||||
|
41 1.78347 4.95586 3.31184 1 4 3
|
||||||
|
93 2.47391 2.57508 3.27574 2 2 3
|
||||||
|
39 0.578712 4.99093 3.85234 0 4 3
|
||||||
|
86 0.144542 4.27264 2.61793 0 4 2
|
||||||
|
5 1.50261 4.9277 4.9755 1 4 4
|
||||||
|
69 3.10555 3.22911 5.00703 3 3 5
|
||||||
|
85 0.965745 3.43479 2.52674 0 3 2
|
||||||
60
examples/python/in.python.wrap
Normal file
60
examples/python/in.python.wrap
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# 3d Lennard-Jones melt with equal- and atom-style variables which
|
||||||
|
# use a Python function wrapper in their formulas
|
||||||
|
|
||||||
|
variable x index 3
|
||||||
|
variable y index 3
|
||||||
|
variable z index 3
|
||||||
|
|
||||||
|
units lj
|
||||||
|
atom_style atomic
|
||||||
|
|
||||||
|
lattice fcc 0.8442
|
||||||
|
region box block 0 $x 0 $y 0 $z
|
||||||
|
create_box 1 box
|
||||||
|
create_atoms 1 box
|
||||||
|
mass 1 1.0
|
||||||
|
|
||||||
|
velocity all create 1.44 87287 loop geom
|
||||||
|
|
||||||
|
pair_style lj/cut 2.5
|
||||||
|
pair_coeff 1 1 1.0 1.0 2.5
|
||||||
|
|
||||||
|
neighbor 0.3 bin
|
||||||
|
neigh_modify delay 0 every 20 check no
|
||||||
|
|
||||||
|
fix 1 all nve
|
||||||
|
|
||||||
|
# define Python truncate() function
|
||||||
|
|
||||||
|
variable foo python truncate
|
||||||
|
python truncate return v_foo input 1 iv_arg format fi here """
|
||||||
|
def truncate(x):
|
||||||
|
return int(x)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# use in equal-style variable
|
||||||
|
|
||||||
|
variable scalar equal py_foo(4.5)
|
||||||
|
print "TRUNCATE ${scalar}"
|
||||||
|
|
||||||
|
# use in atom-style variable
|
||||||
|
# examine dump file to see truncated xyz coords of each atom
|
||||||
|
|
||||||
|
variable xtrunc atom py_foo(x)
|
||||||
|
variable ytrunc atom py_foo(y)
|
||||||
|
variable ztrunc atom py_foo(z)
|
||||||
|
|
||||||
|
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
|
||||||
|
# use in vector-style variable
|
||||||
|
|
||||||
|
compute ke all temp
|
||||||
|
variable ke vector c_ke
|
||||||
|
variable ketrunc vector py_foo(v_ke)
|
||||||
|
thermo_style custom step temp epair v_ketrunc[*6]
|
||||||
|
|
||||||
|
run 100
|
||||||
|
|
||||||
|
print "KE TENSOR ${ketrunc}"
|
||||||
|
|
||||||
|
|
||||||
116
examples/python/log.1May25.python.wrap.g++.1
Normal file
116
examples/python/log.1May25.python.wrap.g++.1
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-270-g2351418c94-modified)
|
||||||
|
# 3d Lennard-Jones melt with equal- and atom-style variables which
|
||||||
|
# use a Python function wrapper in their formulas
|
||||||
|
|
||||||
|
variable x index 3
|
||||||
|
variable y index 3
|
||||||
|
variable z index 3
|
||||||
|
|
||||||
|
units lj
|
||||||
|
atom_style atomic
|
||||||
|
|
||||||
|
lattice fcc 0.8442
|
||||||
|
Lattice spacing in x,y,z = 1.6795962 1.6795962 1.6795962
|
||||||
|
region box block 0 $x 0 $y 0 $z
|
||||||
|
region box block 0 3 0 $y 0 $z
|
||||||
|
region box block 0 3 0 3 0 $z
|
||||||
|
region box block 0 3 0 3 0 3
|
||||||
|
create_box 1 box
|
||||||
|
Created orthogonal box = (0 0 0) to (5.0387886 5.0387886 5.0387886)
|
||||||
|
1 by 1 by 1 MPI processor grid
|
||||||
|
create_atoms 1 box
|
||||||
|
Created 108 atoms
|
||||||
|
using lattice units in orthogonal box = (0 0 0) to (5.0387886 5.0387886 5.0387886)
|
||||||
|
create_atoms CPU = 0.000 seconds
|
||||||
|
mass 1 1.0
|
||||||
|
|
||||||
|
velocity all create 1.44 87287 loop geom
|
||||||
|
|
||||||
|
pair_style lj/cut 2.5
|
||||||
|
pair_coeff 1 1 1.0 1.0 2.5
|
||||||
|
|
||||||
|
neighbor 0.3 bin
|
||||||
|
neigh_modify delay 0 every 20 check no
|
||||||
|
|
||||||
|
fix 1 all nve
|
||||||
|
|
||||||
|
# define Python truncate() function
|
||||||
|
|
||||||
|
variable foo python truncate
|
||||||
|
python truncate return v_foo input 1 iv_arg format fi here """
|
||||||
|
def truncate(x):
|
||||||
|
return int(x)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# use in equal-style variable
|
||||||
|
|
||||||
|
variable scalar equal py_foo(4.5)
|
||||||
|
print "TRUNCATE ${scalar}"
|
||||||
|
TRUNCATE 4
|
||||||
|
|
||||||
|
# use in atom-style variable
|
||||||
|
# examine dump file to see truncated xyz coords of each atom
|
||||||
|
|
||||||
|
variable xtrunc atom py_foo(x)
|
||||||
|
variable ytrunc atom py_foo(y)
|
||||||
|
variable ztrunc atom py_foo(z)
|
||||||
|
|
||||||
|
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
|
||||||
|
# use in vector-style variable
|
||||||
|
|
||||||
|
compute ke all temp
|
||||||
|
variable ke vector c_ke
|
||||||
|
variable ketrunc vector py_foo(v_ke)
|
||||||
|
thermo_style custom step temp epair v_ketrunc[*6]
|
||||||
|
|
||||||
|
run 100
|
||||||
|
Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
|
||||||
|
Neighbor list info ...
|
||||||
|
update: every = 20 steps, delay = 0 steps, check = no
|
||||||
|
max neighbors/atom: 2000, page size: 100000
|
||||||
|
master list distance cutoff = 2.8
|
||||||
|
ghost atom cutoff = 2.8
|
||||||
|
binsize = 1.4, bins = 4 4 4
|
||||||
|
1 neighbor lists, perpetual/occasional/extra = 1 0 0
|
||||||
|
(1) pair lj/cut, perpetual
|
||||||
|
attributes: half, newton on
|
||||||
|
pair build: half/bin/atomonly/newton
|
||||||
|
stencil: half/bin/3d
|
||||||
|
bin: standard
|
||||||
|
Per MPI rank memory allocation (min/avg/max) = 2.598 | 2.598 | 2.598 Mbytes
|
||||||
|
Step Temp E_pair v_ketrunc[1] v_ketrunc[2] v_ketrunc[3] v_ketrunc[4] v_ketrunc[5] v_ketrunc[6]
|
||||||
|
0 1.44 -6.7733681 155 152 154 -10 -4 -6
|
||||||
|
100 0.82217015 -5.8614684 113 65 84 7 -1 -12
|
||||||
|
Loop time of 0.00278186 on 1 procs for 100 steps with 108 atoms
|
||||||
|
|
||||||
|
Performance: 15529161.573 tau/day, 35947.133 timesteps/s, 3.882 Matom-step/s
|
||||||
|
100.0% CPU use with 1 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 0.0018161 | 0.0018161 | 0.0018161 | 0.0 | 65.29
|
||||||
|
Neigh | 0.00057543 | 0.00057543 | 0.00057543 | 0.0 | 20.68
|
||||||
|
Comm | 0.00019634 | 0.00019634 | 0.00019634 | 0.0 | 7.06
|
||||||
|
Output | 0.00012056 | 0.00012056 | 0.00012056 | 0.0 | 4.33
|
||||||
|
Modify | 4.8221e-05 | 4.8221e-05 | 4.8221e-05 | 0.0 | 1.73
|
||||||
|
Other | | 2.516e-05 | | | 0.90
|
||||||
|
|
||||||
|
Nlocal: 108 ave 108 max 108 min
|
||||||
|
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||||
|
Nghost: 980 ave 980 max 980 min
|
||||||
|
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||||
|
Neighs: 4071 ave 4071 max 4071 min
|
||||||
|
Histogram: 1 0 0 0 0 0 0 0 0 0
|
||||||
|
|
||||||
|
Total # of neighbors = 4071
|
||||||
|
Ave neighs/atom = 37.694444
|
||||||
|
Neighbor list builds = 5
|
||||||
|
Dangerous builds not checked
|
||||||
|
|
||||||
|
print "KE TENSOR ${ketrunc}"
|
||||||
|
KE TENSOR [113,65,84,7,-1,-12]
|
||||||
|
|
||||||
|
|
||||||
|
Total wall time: 0:00:00
|
||||||
116
examples/python/log.1May25.python.wrap.g++.4
Normal file
116
examples/python/log.1May25.python.wrap.g++.4
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-270-g2351418c94-modified)
|
||||||
|
# 3d Lennard-Jones melt with equal- and atom-style variables which
|
||||||
|
# use a Python function wrapper in their formulas
|
||||||
|
|
||||||
|
variable x index 3
|
||||||
|
variable y index 3
|
||||||
|
variable z index 3
|
||||||
|
|
||||||
|
units lj
|
||||||
|
atom_style atomic
|
||||||
|
|
||||||
|
lattice fcc 0.8442
|
||||||
|
Lattice spacing in x,y,z = 1.6795962 1.6795962 1.6795962
|
||||||
|
region box block 0 $x 0 $y 0 $z
|
||||||
|
region box block 0 3 0 $y 0 $z
|
||||||
|
region box block 0 3 0 3 0 $z
|
||||||
|
region box block 0 3 0 3 0 3
|
||||||
|
create_box 1 box
|
||||||
|
Created orthogonal box = (0 0 0) to (5.0387886 5.0387886 5.0387886)
|
||||||
|
1 by 2 by 2 MPI processor grid
|
||||||
|
create_atoms 1 box
|
||||||
|
Created 108 atoms
|
||||||
|
using lattice units in orthogonal box = (0 0 0) to (5.0387886 5.0387886 5.0387886)
|
||||||
|
create_atoms CPU = 0.000 seconds
|
||||||
|
mass 1 1.0
|
||||||
|
|
||||||
|
velocity all create 1.44 87287 loop geom
|
||||||
|
|
||||||
|
pair_style lj/cut 2.5
|
||||||
|
pair_coeff 1 1 1.0 1.0 2.5
|
||||||
|
|
||||||
|
neighbor 0.3 bin
|
||||||
|
neigh_modify delay 0 every 20 check no
|
||||||
|
|
||||||
|
fix 1 all nve
|
||||||
|
|
||||||
|
# define Python truncate() function
|
||||||
|
|
||||||
|
variable foo python truncate
|
||||||
|
python truncate return v_foo input 1 iv_arg format fi here """
|
||||||
|
def truncate(x):
|
||||||
|
return int(x)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# use in equal-style variable
|
||||||
|
|
||||||
|
variable scalar equal py_foo(4.5)
|
||||||
|
print "TRUNCATE ${scalar}"
|
||||||
|
TRUNCATE 4
|
||||||
|
|
||||||
|
# use in atom-style variable
|
||||||
|
# examine dump file to see truncated xyz coords of each atom
|
||||||
|
|
||||||
|
variable xtrunc atom py_foo(x)
|
||||||
|
variable ytrunc atom py_foo(y)
|
||||||
|
variable ztrunc atom py_foo(z)
|
||||||
|
|
||||||
|
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
|
||||||
|
|
||||||
|
# use in vector-style variable
|
||||||
|
|
||||||
|
compute ke all temp
|
||||||
|
variable ke vector c_ke
|
||||||
|
variable ketrunc vector py_foo(v_ke)
|
||||||
|
thermo_style custom step temp epair v_ketrunc[*6]
|
||||||
|
|
||||||
|
run 100
|
||||||
|
Generated 0 of 0 mixed pair_coeff terms from geometric mixing rule
|
||||||
|
Neighbor list info ...
|
||||||
|
update: every = 20 steps, delay = 0 steps, check = no
|
||||||
|
max neighbors/atom: 2000, page size: 100000
|
||||||
|
master list distance cutoff = 2.8
|
||||||
|
ghost atom cutoff = 2.8
|
||||||
|
binsize = 1.4, bins = 4 4 4
|
||||||
|
1 neighbor lists, perpetual/occasional/extra = 1 0 0
|
||||||
|
(1) pair lj/cut, perpetual
|
||||||
|
attributes: half, newton on
|
||||||
|
pair build: half/bin/atomonly/newton
|
||||||
|
stencil: half/bin/3d
|
||||||
|
bin: standard
|
||||||
|
Per MPI rank memory allocation (min/avg/max) = 2.59 | 2.59 | 2.59 Mbytes
|
||||||
|
Step Temp E_pair v_ketrunc[1] v_ketrunc[2] v_ketrunc[3] v_ketrunc[4] v_ketrunc[5] v_ketrunc[6]
|
||||||
|
0 1.44 -6.7733681 155 152 154 -10 -4 -6
|
||||||
|
100 0.82217015 -5.8614684 113 65 84 7 -1 -12
|
||||||
|
Loop time of 0.00268845 on 4 procs for 100 steps with 108 atoms
|
||||||
|
|
||||||
|
Performance: 16068745.964 tau/day, 37196.171 timesteps/s, 4.017 Matom-step/s
|
||||||
|
66.7% CPU use with 4 MPI tasks x no OpenMP threads
|
||||||
|
|
||||||
|
MPI task timing breakdown:
|
||||||
|
Section | min time | avg time | max time |%varavg| %total
|
||||||
|
---------------------------------------------------------------
|
||||||
|
Pair | 0.00043389 | 0.00051695 | 0.00061255 | 0.0 | 19.23
|
||||||
|
Neigh | 0.00017121 | 0.00018976 | 0.00019891 | 0.0 | 7.06
|
||||||
|
Comm | 0.0017423 | 0.0018487 | 0.0019509 | 0.2 | 68.76
|
||||||
|
Output | 6.7449e-05 | 6.9998e-05 | 7.5195e-05 | 0.0 | 2.60
|
||||||
|
Modify | 2.1329e-05 | 2.2855e-05 | 2.4821e-05 | 0.0 | 0.85
|
||||||
|
Other | | 4.018e-05 | | | 1.49
|
||||||
|
|
||||||
|
Nlocal: 27 ave 30 max 25 min
|
||||||
|
Histogram: 1 0 1 0 1 0 0 0 0 1
|
||||||
|
Nghost: 614 ave 616 max 612 min
|
||||||
|
Histogram: 1 0 1 0 0 0 0 1 0 1
|
||||||
|
Neighs: 1017.75 ave 1149 max 894 min
|
||||||
|
Histogram: 1 1 0 0 0 0 0 1 0 1
|
||||||
|
|
||||||
|
Total # of neighbors = 4071
|
||||||
|
Ave neighs/atom = 37.694444
|
||||||
|
Neighbor list builds = 5
|
||||||
|
Dangerous builds not checked
|
||||||
|
|
||||||
|
print "KE TENSOR ${ketrunc}"
|
||||||
|
KE TENSOR [113,65,84,7,-1,-12]
|
||||||
|
|
||||||
|
|
||||||
|
Total wall time: 0:00:00
|
||||||
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "python_impl.h"
|
#include "python_impl.h"
|
||||||
|
|
||||||
|
#include "comm.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -62,6 +63,7 @@
|
|||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
enum { NONE, INT, DOUBLE, STRING, PTR };
|
enum { NONE, INT, DOUBLE, STRING, PTR };
|
||||||
|
enum { VALUE, VARIABLE, INTERNALVAR };
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
@ -94,20 +96,27 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
// Inform python intialization scheme of the mliappy module.
|
// Inform python intialization scheme of the mliappy module.
|
||||||
// This -must- happen before python is initialized.
|
// This -must- happen before python is initialized.
|
||||||
int err = PyImport_AppendInittab("mliap_model_python_couple", PyInit_mliap_model_python_couple);
|
int err = PyImport_AppendInittab("mliap_model_python_couple", PyInit_mliap_model_python_couple);
|
||||||
if (err) error->all(FLERR, "Could not register MLIAPPY embedded python module.");
|
if (err)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE, "Could not register MLIAPPY embedded python module.");
|
||||||
|
|
||||||
err = PyImport_AppendInittab("mliap_unified_couple", PyInit_mliap_unified_couple);
|
err = PyImport_AppendInittab("mliap_unified_couple", PyInit_mliap_unified_couple);
|
||||||
if (err) error->all(FLERR, "Could not register MLIAPPY unified embedded python module.");
|
if (err)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Could not register MLIAPPY unified embedded python module.");
|
||||||
|
|
||||||
#ifdef LMP_KOKKOS
|
#ifdef LMP_KOKKOS
|
||||||
// Inform python intialization scheme of the mliappy module.
|
// Inform python intialization scheme of the mliappy module.
|
||||||
// This -must- happen before python is initialized.
|
// This -must- happen before python is initialized.
|
||||||
err = PyImport_AppendInittab("mliap_model_python_couple_kokkos",
|
err = PyImport_AppendInittab("mliap_model_python_couple_kokkos",
|
||||||
PyInit_mliap_model_python_couple_kokkos);
|
PyInit_mliap_model_python_couple_kokkos);
|
||||||
if (err) error->all(FLERR, "Could not register MLIAPPY embedded python KOKKOS module.");
|
if (err)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Could not register MLIAPPY embedded python KOKKOS module.");
|
||||||
|
|
||||||
err = PyImport_AppendInittab("mliap_unified_couple_kokkos", PyInit_mliap_unified_couple_kokkos);
|
err = PyImport_AppendInittab("mliap_unified_couple_kokkos", PyInit_mliap_unified_couple_kokkos);
|
||||||
if (err) error->all(FLERR, "Could not register MLIAPPY unified embedded python KOKKOS module.");
|
if (err)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Could not register MLIAPPY unified embedded python KOKKOS module.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -129,7 +138,7 @@ PythonImpl::PythonImpl(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
PyUtils::GIL lock;
|
PyUtils::GIL lock;
|
||||||
|
|
||||||
PyObject *pModule = PyImport_AddModule("__main__");
|
PyObject *pModule = PyImport_AddModule("__main__");
|
||||||
if (!pModule) error->all(FLERR, "Could not initialize embedded Python");
|
if (!pModule) error->all(FLERR, Error::NOLASTLINE, "Could not initialize embedded Python");
|
||||||
|
|
||||||
pyMain = (void *) pModule;
|
pyMain = (void *) pModule;
|
||||||
}
|
}
|
||||||
@ -158,23 +167,31 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
{
|
{
|
||||||
if (narg < 2) utils::missing_cmd_args(FLERR, "python", error);
|
if (narg < 2) utils::missing_cmd_args(FLERR, "python", error);
|
||||||
|
|
||||||
// if invoke is only keyword, invoke the previously defined function
|
// if invoke keyword is used, invoke the previously defined function
|
||||||
|
|
||||||
if (narg == 2 && strcmp(arg[1], "invoke") == 0) {
|
if (strcmp(arg[1], "invoke") == 0) {
|
||||||
int ifunc = find(arg[0]);
|
int ifunc = find(arg[0]);
|
||||||
if (ifunc < 0) error->all(FLERR, "Python invoke of unknown function: {}", arg[0]);
|
if (ifunc < 0)
|
||||||
|
error->all(FLERR, Error::ARGZERO, "Python invoke of unknown function: {}", arg[0]);
|
||||||
|
|
||||||
char *str = nullptr;
|
char *str = nullptr;
|
||||||
if (pfuncs[ifunc].noutput) {
|
if (pfuncs[ifunc].noutput) {
|
||||||
str = input->variable->pythonstyle(pfuncs[ifunc].ovarname, pfuncs[ifunc].name);
|
str = input->variable->pythonstyle(pfuncs[ifunc].ovarname, pfuncs[ifunc].name);
|
||||||
if (!str)
|
if (!str)
|
||||||
error->all(FLERR,
|
error->all(
|
||||||
"Python variable {} does not match variable {} "
|
FLERR, Error::ARGZERO,
|
||||||
"registered with Python function {}",
|
"Python variable {} does not match variable {} registered with Python function {}",
|
||||||
arg[0], pfuncs[ifunc].ovarname, pfuncs[ifunc].name);
|
arg[0], pfuncs[ifunc].ovarname, pfuncs[ifunc].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
invoke_function(ifunc, str);
|
bool logreturn = false;
|
||||||
|
if (narg == 3 && strcmp(arg[2], "logreturn") == 0) logreturn = true;
|
||||||
|
|
||||||
|
invoke_function(ifunc, str, nullptr);
|
||||||
|
|
||||||
|
if (logreturn && str && (comm->me == 0))
|
||||||
|
utils::logmesg(lmp, "Invoked python function {} returned {}\n", arg[0], str);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +206,7 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
if (platform::file_is_readable(arg[1]))
|
if (platform::file_is_readable(arg[1]))
|
||||||
err = execute_file(arg[1]);
|
err = execute_file(arg[1]);
|
||||||
else
|
else
|
||||||
error->all(FLERR, "Could not open python source file {} for processing", arg[1]);
|
error->all(FLERR, 1, "Could not open python source file {} for processing", arg[1]);
|
||||||
}
|
}
|
||||||
if (err) error->all(FLERR, "Failure in python source command");
|
if (err) error->all(FLERR, "Failure in python source command");
|
||||||
|
|
||||||
@ -213,7 +230,8 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
if (strcmp(arg[iarg], "input") == 0) {
|
if (strcmp(arg[iarg], "input") == 0) {
|
||||||
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "python input", error);
|
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "python input", error);
|
||||||
ninput = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
ninput = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||||
if (ninput < 0) error->all(FLERR, "Invalid number of python input arguments: {}", ninput);
|
if (ninput < 0)
|
||||||
|
error->all(FLERR, iarg + 1, "Invalid number of python input arguments: {}", ninput);
|
||||||
iarg += 2;
|
iarg += 2;
|
||||||
delete[] istr;
|
delete[] istr;
|
||||||
istr = new char *[ninput];
|
istr = new char *[ninput];
|
||||||
@ -232,7 +250,8 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
} else if (strcmp(arg[iarg], "length") == 0) {
|
} else if (strcmp(arg[iarg], "length") == 0) {
|
||||||
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "python length", error);
|
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "python length", error);
|
||||||
length_longstr = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
length_longstr = utils::inumeric(FLERR, arg[iarg + 1], false, lmp);
|
||||||
if (length_longstr <= 0) error->all(FLERR, "Invalid python return value length");
|
if (length_longstr <= 0)
|
||||||
|
error->all(FLERR, iarg + 1, "Invalid python return value length {}", length_longstr);
|
||||||
iarg += 2;
|
iarg += 2;
|
||||||
} else if (strcmp(arg[iarg], "file") == 0) {
|
} else if (strcmp(arg[iarg], "file") == 0) {
|
||||||
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "python file", error);
|
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "python file", error);
|
||||||
@ -247,15 +266,18 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
existflag = 1;
|
existflag = 1;
|
||||||
iarg++;
|
iarg++;
|
||||||
} else
|
} else
|
||||||
error->all(FLERR, "Unknown python command keyword: {}", arg[iarg]);
|
error->all(FLERR, iarg, "Unknown python command keyword: {}", arg[iarg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pyfile && herestr)
|
if (pyfile && herestr)
|
||||||
error->all(FLERR, "Must not use python 'file' and 'here' keywords at the same time");
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Must not use python 'file' and 'here' keywords at the same time");
|
||||||
if (pyfile && existflag)
|
if (pyfile && existflag)
|
||||||
error->all(FLERR, "Must not use python 'file' and 'exists' keywords at the same time");
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Must not use python 'file' and 'exists' keywords at the same time");
|
||||||
if (herestr && existflag)
|
if (herestr && existflag)
|
||||||
error->all(FLERR, "Must not use python 'here' and 'exists' keywords at the same time");
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Must not use python 'here' and 'exists' keywords at the same time");
|
||||||
|
|
||||||
// create or overwrite entry in pfuncs vector with name = arg[0]
|
// create or overwrite entry in pfuncs vector with name = arg[0]
|
||||||
|
|
||||||
@ -273,13 +295,13 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
|
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
PyUtils::Print_Errors();
|
PyUtils::Print_Errors();
|
||||||
error->all(FLERR, "Could not open Python file: {}", pyfile);
|
error->all(FLERR, Error::NOLASTLINE, "Could not open Python file: {}", pyfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = PyRun_SimpleFile(fp, pyfile);
|
int err = PyRun_SimpleFile(fp, pyfile);
|
||||||
if (err) {
|
if (err) {
|
||||||
PyUtils::Print_Errors();
|
PyUtils::Print_Errors();
|
||||||
error->all(FLERR, "Could not process Python file: {}", pyfile);
|
error->all(FLERR, Error::NOLASTLINE, "Could not process Python file: {}", pyfile);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
@ -287,7 +309,7 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
int err = PyRun_SimpleString(herestr);
|
int err = PyRun_SimpleString(herestr);
|
||||||
if (err) {
|
if (err) {
|
||||||
PyUtils::Print_Errors();
|
PyUtils::Print_Errors();
|
||||||
error->all(FLERR, "Could not process Python string: {}", herestr);
|
error->all(FLERR, Error::NOLASTLINE, "Could not process Python string: {}", herestr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,12 +320,12 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
|
|
||||||
if (!pFunc) {
|
if (!pFunc) {
|
||||||
PyUtils::Print_Errors();
|
PyUtils::Print_Errors();
|
||||||
error->all(FLERR, "Could not find Python function {}", pfuncs[ifunc].name);
|
error->all(FLERR, Error::NOLASTLINE, "Could not find Python function {}", pfuncs[ifunc].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyCallable_Check(pFunc)) {
|
if (!PyCallable_Check(pFunc)) {
|
||||||
PyUtils::Print_Errors();
|
PyUtils::Print_Errors();
|
||||||
error->all(FLERR, "Python function {} is not callable", pfuncs[ifunc].name);
|
error->all(FLERR, Error::NOLASTLINE, "Python function {} is not callable", pfuncs[ifunc].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pfuncs[ifunc].pFunc = (void *) pFunc;
|
pfuncs[ifunc].pFunc = (void *) pFunc;
|
||||||
@ -317,7 +339,7 @@ void PythonImpl::command(int narg, char **arg)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
void PythonImpl::invoke_function(int ifunc, char *result)
|
void PythonImpl::invoke_function(int ifunc, char *result, double *dvalue)
|
||||||
{
|
{
|
||||||
PyUtils::GIL lock;
|
PyUtils::GIL lock;
|
||||||
PyObject *pValue;
|
PyObject *pValue;
|
||||||
@ -331,44 +353,54 @@ void PythonImpl::invoke_function(int ifunc, char *result)
|
|||||||
PyObject *pArgs = PyTuple_New(ninput);
|
PyObject *pArgs = PyTuple_New(ninput);
|
||||||
|
|
||||||
if (!pArgs)
|
if (!pArgs)
|
||||||
error->all(FLERR, "Could not prepare arguments for Python function {}", pfuncs[ifunc].name);
|
error->all(FLERR, Error::NOLASTLINE, "Could not prepare arguments for Python function {}",
|
||||||
|
pfuncs[ifunc].name);
|
||||||
|
|
||||||
for (int i = 0; i < ninput; i++) {
|
for (int i = 0; i < ninput; i++) {
|
||||||
int itype = pfuncs[ifunc].itype[i];
|
int itype = pfuncs[ifunc].itype[i];
|
||||||
if (itype == INT) {
|
if (itype == INT) {
|
||||||
if (pfuncs[ifunc].ivarflag[i]) {
|
if (pfuncs[ifunc].ivarflag[i] == VARIABLE) {
|
||||||
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
||||||
if (!str)
|
if (!str)
|
||||||
error->all(FLERR, "Could not evaluate Python function {} input variable: {}",
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]);
|
"Could not evaluate Python function {} input variable: {}", pfuncs[ifunc].name,
|
||||||
|
pfuncs[ifunc].svalue[i]);
|
||||||
pValue = PY_INT_FROM_LONG(PY_LONG_FROM_STRING(str));
|
pValue = PY_INT_FROM_LONG(PY_LONG_FROM_STRING(str));
|
||||||
|
} else if (pfuncs[ifunc].ivarflag[i] == INTERNALVAR) {
|
||||||
|
double value = input->variable->compute_equal(pfuncs[ifunc].internal_var[i]);
|
||||||
|
pValue = PyLong_FromDouble(value);
|
||||||
} else {
|
} else {
|
||||||
pValue = PY_INT_FROM_LONG(pfuncs[ifunc].ivalue[i]);
|
pValue = PY_INT_FROM_LONG(pfuncs[ifunc].ivalue[i]);
|
||||||
}
|
}
|
||||||
} else if (itype == DOUBLE) {
|
} else if (itype == DOUBLE) {
|
||||||
if (pfuncs[ifunc].ivarflag[i]) {
|
if (pfuncs[ifunc].ivarflag[i] == VARIABLE) {
|
||||||
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
||||||
if (!str)
|
if (!str)
|
||||||
error->all(FLERR, "Could not evaluate Python function {} input variable: {}",
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]);
|
"Could not evaluate Python function {} input variable: {}", pfuncs[ifunc].name,
|
||||||
|
pfuncs[ifunc].svalue[i]);
|
||||||
pValue = PyFloat_FromDouble(std::stod(str));
|
pValue = PyFloat_FromDouble(std::stod(str));
|
||||||
|
} else if (pfuncs[ifunc].ivarflag[i] == INTERNALVAR) {
|
||||||
|
double value = input->variable->compute_equal(pfuncs[ifunc].internal_var[i]);
|
||||||
|
pValue = PyFloat_FromDouble(value);
|
||||||
} else {
|
} else {
|
||||||
pValue = PyFloat_FromDouble(pfuncs[ifunc].dvalue[i]);
|
pValue = PyFloat_FromDouble(pfuncs[ifunc].dvalue[i]);
|
||||||
}
|
}
|
||||||
} else if (itype == STRING) {
|
} else if (itype == STRING) {
|
||||||
if (pfuncs[ifunc].ivarflag[i]) {
|
if (pfuncs[ifunc].ivarflag[i] == VARIABLE) {
|
||||||
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
|
||||||
if (!str)
|
if (!str)
|
||||||
error->all(FLERR, "Could not evaluate Python function {} input variable: {}",
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]);
|
"Could not evaluate Python function {} input variable: {}", pfuncs[ifunc].name,
|
||||||
|
pfuncs[ifunc].svalue[i]);
|
||||||
pValue = PyUnicode_FromString(str);
|
pValue = PyUnicode_FromString(str);
|
||||||
} else {
|
} else {
|
||||||
pValue = PyUnicode_FromString(pfuncs[ifunc].svalue[i]);
|
pValue = PyUnicode_FromString(pfuncs[ifunc].svalue[i]);
|
||||||
}
|
}
|
||||||
} else if (itype == PTR) {
|
} else if (itype == PTR) {
|
||||||
pValue = PyCapsule_New((void *)lmp, nullptr, nullptr);
|
pValue = PyCapsule_New((void *) lmp, nullptr, nullptr);
|
||||||
} else {
|
} else {
|
||||||
error->all(FLERR, "Unsupported variable type: {}", itype);
|
error->all(FLERR, Error::NOLASTLINE, "Unsupported variable type: {}", itype);
|
||||||
}
|
}
|
||||||
PyTuple_SetItem(pArgs, i, pValue);
|
PyTuple_SetItem(pArgs, i, pValue);
|
||||||
}
|
}
|
||||||
@ -381,29 +413,37 @@ void PythonImpl::invoke_function(int ifunc, char *result)
|
|||||||
|
|
||||||
if (!pValue) {
|
if (!pValue) {
|
||||||
PyUtils::Print_Errors();
|
PyUtils::Print_Errors();
|
||||||
error->one(FLERR, "Python evaluation of function {} failed", pfuncs[ifunc].name);
|
error->one(FLERR, Error::NOLASTLINE, "Python evaluation of function {} failed",
|
||||||
|
pfuncs[ifunc].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function returned a value
|
// function returned a value
|
||||||
// assign it to result string stored by python-style variable
|
// if result is non-NULL, assign to result string stored by python-style variable
|
||||||
// or if user specified a length, assign it to longstr
|
// or if value is string and user specified a length, assign it to longstr
|
||||||
|
// if dvalue is non-NULL, assign numeric value directly to dvalue
|
||||||
|
|
||||||
if (pfuncs[ifunc].noutput) {
|
if (pfuncs[ifunc].noutput) {
|
||||||
int otype = pfuncs[ifunc].otype;
|
int otype = pfuncs[ifunc].otype;
|
||||||
if (otype == INT) {
|
if (otype == INT) {
|
||||||
auto value = fmt::format("{}", PY_INT_AS_LONG(pValue));
|
if (dvalue) *dvalue = (double) PY_INT_AS_LONG(pValue);
|
||||||
strncpy(result, value.c_str(), Variable::VALUELENGTH - 1);
|
if (result) {
|
||||||
|
auto value = fmt::format("{}", PY_INT_AS_LONG(pValue));
|
||||||
|
strncpy(result, value.c_str(), Variable::VALUELENGTH - 1);
|
||||||
|
}
|
||||||
} else if (otype == DOUBLE) {
|
} else if (otype == DOUBLE) {
|
||||||
auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue));
|
if (dvalue) *dvalue = PyFloat_AsDouble(pValue);
|
||||||
strncpy(result, value.c_str(), Variable::VALUELENGTH - 1);
|
if (result) {
|
||||||
|
auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue));
|
||||||
|
strncpy(result, value.c_str(), Variable::VALUELENGTH - 1);
|
||||||
|
}
|
||||||
} else if (otype == STRING) {
|
} else if (otype == STRING) {
|
||||||
const char *pystr = PyUnicode_AsUTF8(pValue);
|
const char *pystr = PyUnicode_AsUTF8(pValue);
|
||||||
if (pfuncs[ifunc].longstr)
|
if (pfuncs[ifunc].longstr)
|
||||||
strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr);
|
strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr);
|
||||||
else
|
if (result) strncpy(result, pystr, Variable::VALUELENGTH - 1);
|
||||||
strncpy(result, pystr, Variable::VALUELENGTH - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_CLEAR(pValue);
|
Py_CLEAR(pValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,15 +456,80 @@ int PythonImpl::find(const char *name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ---------------------------------------------------------------------
|
||||||
|
called by Variable class when a python-style variable is evaluated
|
||||||
|
this will call invoke_function() in this class
|
||||||
|
either via Variable::retrieve() or Variable::equalstyle
|
||||||
|
retrieve calls with numeric = 0, equalstyle with numeric = 1
|
||||||
|
ensure name matches a Python function
|
||||||
|
ensure the Python function produces an output
|
||||||
|
ensure the Python function outputs to the matching python-style variable
|
||||||
|
ensure a string is returned only if retrieve() is the caller
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
|
||||||
int PythonImpl::variable_match(const char *name, const char *varname, int numeric)
|
int PythonImpl::function_match(const char *name, const char *varname, int numeric, Error *error)
|
||||||
{
|
{
|
||||||
int ifunc = find(name);
|
int ifunc = find(name);
|
||||||
if (ifunc < 0) return -1;
|
|
||||||
if (pfuncs[ifunc].noutput == 0) return -2;
|
if (ifunc < 0)
|
||||||
if (strcmp(pfuncs[ifunc].ovarname, varname) != 0) return -3;
|
error->all(FLERR, Error::NOLASTLINE, "Python function {} specified by variable {} not found",
|
||||||
if (numeric && pfuncs[ifunc].otype == STRING) return -4;
|
name, varname);
|
||||||
|
if (pfuncs[ifunc].noutput == 0)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Python function {} for variable {} does not return a value", name, varname);
|
||||||
|
if (strcmp(pfuncs[ifunc].ovarname, varname) != 0)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Python function {} and variable {} do not link to each other", name, varname);
|
||||||
|
if (numeric && pfuncs[ifunc].otype == STRING)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE, "Python function {} for variable {} returns a string",
|
||||||
|
name, varname);
|
||||||
|
|
||||||
|
return ifunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------
|
||||||
|
called by Variable class when evaluating a Python wrapper function
|
||||||
|
which will call invoke_function()
|
||||||
|
either via equal-style or atom-style variable formula
|
||||||
|
the latter calls invoke_function() once per atom
|
||||||
|
same error checks as function_match() plus 2 new ones
|
||||||
|
ensure match of number of Python function args mapped to internal-style variables
|
||||||
|
ensure each internal-style variable still exists
|
||||||
|
must check now in case user input script deleted variables between runs
|
||||||
|
which could invalidate indices set in create_event()
|
||||||
|
other classes avoid this issue by setting variable indices in their init() method
|
||||||
|
--------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int PythonImpl::wrapper_match(const char *name, const char *varname, int narg, int *argvars,
|
||||||
|
Error *error)
|
||||||
|
{
|
||||||
|
int ifunc = function_match(name, varname, 1, error);
|
||||||
|
if (ifunc < 0) return ifunc;
|
||||||
|
|
||||||
|
int internal_count = 0;
|
||||||
|
for (int i = 0; i < pfuncs[ifunc].ninput; i++)
|
||||||
|
if (pfuncs[ifunc].ivarflag[i] == INTERNALVAR) internal_count++;
|
||||||
|
if (internal_count != narg)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Python function {} does not use {} internal variable args", name, narg);
|
||||||
|
|
||||||
|
// set argvars of internal-style variables for use by Variable class
|
||||||
|
// in Python wrapper functions
|
||||||
|
// also set internal_var for use by invoke_function()
|
||||||
|
// so that invoke_function() is as fast as possible for args which are internal-style vars
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < pfuncs[ifunc].ninput; i++) {
|
||||||
|
if (pfuncs[ifunc].ivarflag[i] == INTERNALVAR) {
|
||||||
|
int ivar = input->variable->find(pfuncs[ifunc].svalue[i]);
|
||||||
|
if (ivar < 0)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE, "Python function {} cannot find internal variable {}",
|
||||||
|
name, pfuncs[ifunc].svalue[i]);
|
||||||
|
pfuncs[ifunc].internal_var[i] = ivar;
|
||||||
|
argvars[j++] = ivar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ifunc;
|
return ifunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,9 +562,10 @@ int PythonImpl::create_entry(char *name, int ninput, int noutput, int length_lon
|
|||||||
pfuncs[ifunc].noutput = noutput;
|
pfuncs[ifunc].noutput = noutput;
|
||||||
|
|
||||||
if (!format && ninput + noutput)
|
if (!format && ninput + noutput)
|
||||||
error->all(FLERR, "Missing python format keyword");
|
error->all(FLERR, Error::NOLASTLINE, "Missing python format keyword");
|
||||||
else if (format && ((int) strlen(format) != ninput + noutput))
|
else if (format && ((int) strlen(format) != ninput + noutput))
|
||||||
error->all(FLERR, "Input/output arguments ({}) and format characters ({}) are inconsistent",
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Input/output arguments ({}) and format characters ({}) are inconsistent",
|
||||||
(ninput + noutput), strlen(format));
|
(ninput + noutput), strlen(format));
|
||||||
|
|
||||||
// process inputs as values or variables
|
// process inputs as values or variables
|
||||||
@ -469,6 +575,7 @@ int PythonImpl::create_entry(char *name, int ninput, int noutput, int length_lon
|
|||||||
pfuncs[ifunc].ivalue = new int[ninput];
|
pfuncs[ifunc].ivalue = new int[ninput];
|
||||||
pfuncs[ifunc].dvalue = new double[ninput];
|
pfuncs[ifunc].dvalue = new double[ninput];
|
||||||
pfuncs[ifunc].svalue = new char *[ninput];
|
pfuncs[ifunc].svalue = new char *[ninput];
|
||||||
|
pfuncs[ifunc].internal_var = new int[ninput];
|
||||||
|
|
||||||
for (int i = 0; i < ninput; i++) {
|
for (int i = 0; i < ninput; i++) {
|
||||||
pfuncs[ifunc].svalue[i] = nullptr;
|
pfuncs[ifunc].svalue[i] = nullptr;
|
||||||
@ -476,37 +583,64 @@ int PythonImpl::create_entry(char *name, int ninput, int noutput, int length_lon
|
|||||||
if (type == 'i') {
|
if (type == 'i') {
|
||||||
pfuncs[ifunc].itype[i] = INT;
|
pfuncs[ifunc].itype[i] = INT;
|
||||||
if (utils::strmatch(istr[i], "^v_")) {
|
if (utils::strmatch(istr[i], "^v_")) {
|
||||||
pfuncs[ifunc].ivarflag[i] = 1;
|
pfuncs[ifunc].ivarflag[i] = VARIABLE;
|
||||||
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 2);
|
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 2);
|
||||||
|
} else if (utils::strmatch(istr[i], "^iv_")) {
|
||||||
|
pfuncs[ifunc].ivarflag[i] = INTERNALVAR;
|
||||||
|
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 3);
|
||||||
|
char *vname = pfuncs[ifunc].svalue[i];
|
||||||
|
int ivar = input->variable->find(vname);
|
||||||
|
if (ivar < 0) { // create internal variable if does not exist
|
||||||
|
input->variable->internal_create(vname, 0.0);
|
||||||
|
ivar = input->variable->find(vname);
|
||||||
|
}
|
||||||
|
if (!input->variable->internalstyle(ivar))
|
||||||
|
error->all(FLERR, Error::NOLASTLINE, "Variable {} for python command is invalid style",
|
||||||
|
vname);
|
||||||
} else {
|
} else {
|
||||||
pfuncs[ifunc].ivarflag[i] = 0;
|
pfuncs[ifunc].ivarflag[i] = VALUE;
|
||||||
pfuncs[ifunc].ivalue[i] = utils::inumeric(FLERR, istr[i], false, lmp);
|
pfuncs[ifunc].ivalue[i] = utils::inumeric(FLERR, istr[i], false, lmp);
|
||||||
}
|
}
|
||||||
} else if (type == 'f') {
|
} else if (type == 'f') {
|
||||||
pfuncs[ifunc].itype[i] = DOUBLE;
|
pfuncs[ifunc].itype[i] = DOUBLE;
|
||||||
if (utils::strmatch(istr[i], "^v_")) {
|
if (utils::strmatch(istr[i], "^v_")) {
|
||||||
pfuncs[ifunc].ivarflag[i] = 1;
|
pfuncs[ifunc].ivarflag[i] = VARIABLE;
|
||||||
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 2);
|
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 2);
|
||||||
|
} else if (utils::strmatch(istr[i], "^iv_")) {
|
||||||
|
pfuncs[ifunc].ivarflag[i] = INTERNALVAR;
|
||||||
|
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 3);
|
||||||
|
char *vname = pfuncs[ifunc].svalue[i];
|
||||||
|
int ivar = input->variable->find(vname);
|
||||||
|
if (ivar < 0) { // create internal variable if does not exist
|
||||||
|
input->variable->internal_create(vname, 0.0);
|
||||||
|
ivar = input->variable->find(vname);
|
||||||
|
}
|
||||||
|
if (!input->variable->internalstyle(ivar))
|
||||||
|
error->all(FLERR, Error::NOLASTLINE, "Variable {} for python command is invalid style",
|
||||||
|
vname);
|
||||||
} else {
|
} else {
|
||||||
pfuncs[ifunc].ivarflag[i] = 0;
|
pfuncs[ifunc].ivarflag[i] = VALUE;
|
||||||
pfuncs[ifunc].dvalue[i] = utils::numeric(FLERR, istr[i], false, lmp);
|
pfuncs[ifunc].dvalue[i] = utils::numeric(FLERR, istr[i], false, lmp);
|
||||||
}
|
}
|
||||||
} else if (type == 's') {
|
} else if (type == 's') {
|
||||||
pfuncs[ifunc].itype[i] = STRING;
|
pfuncs[ifunc].itype[i] = STRING;
|
||||||
if (utils::strmatch(istr[i], "^v_")) {
|
if (utils::strmatch(istr[i], "^v_")) {
|
||||||
pfuncs[ifunc].ivarflag[i] = 1;
|
pfuncs[ifunc].ivarflag[i] = VARIABLE;
|
||||||
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 2);
|
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i] + 2);
|
||||||
|
} else if (utils::strmatch(istr[i], "^iv_")) {
|
||||||
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Input argument {} cannot be internal variable with string format", istr[i]);
|
||||||
} else {
|
} else {
|
||||||
pfuncs[ifunc].ivarflag[i] = 0;
|
pfuncs[ifunc].ivarflag[i] = VALUE;
|
||||||
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i]);
|
pfuncs[ifunc].svalue[i] = utils::strdup(istr[i]);
|
||||||
}
|
}
|
||||||
} else if (type == 'p') {
|
} else if (type == 'p') {
|
||||||
pfuncs[ifunc].ivarflag[i] = 0;
|
pfuncs[ifunc].ivarflag[i] = VALUE;
|
||||||
pfuncs[ifunc].itype[i] = PTR;
|
pfuncs[ifunc].itype[i] = PTR;
|
||||||
if (strcmp(istr[i], "SELF") != 0) error->all(FLERR, "Invalid python command");
|
if (strcmp(istr[i], "SELF") != 0) error->all(FLERR, "Invalid python command");
|
||||||
|
|
||||||
} else
|
} else
|
||||||
error->all(FLERR, "Invalid python format character: {}", type);
|
error->all(FLERR, Error::NOLASTLINE, "Invalid python format character: {}", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process output as value or variable
|
// process output as value or variable
|
||||||
@ -523,17 +657,19 @@ int PythonImpl::create_entry(char *name, int ninput, int noutput, int length_lon
|
|||||||
else if (type == 's')
|
else if (type == 's')
|
||||||
pfuncs[ifunc].otype = STRING;
|
pfuncs[ifunc].otype = STRING;
|
||||||
else
|
else
|
||||||
error->all(FLERR, "Invalid python return format character: {}", type);
|
error->all(FLERR, Error::NOLASTLINE, "Invalid python return format character: {}", type);
|
||||||
|
|
||||||
if (length_longstr) {
|
if (length_longstr) {
|
||||||
if (pfuncs[ifunc].otype != STRING)
|
if (pfuncs[ifunc].otype != STRING)
|
||||||
error->all(FLERR, "Python command length keyword cannot be used unless output is a string");
|
error->all(FLERR, Error::NOLASTLINE,
|
||||||
|
"Python command length keyword cannot be used unless output is a string");
|
||||||
pfuncs[ifunc].length_longstr = length_longstr;
|
pfuncs[ifunc].length_longstr = length_longstr;
|
||||||
pfuncs[ifunc].longstr = new char[length_longstr + 1];
|
pfuncs[ifunc].longstr = new char[length_longstr + 1];
|
||||||
pfuncs[ifunc].longstr[length_longstr] = '\0';
|
pfuncs[ifunc].longstr[length_longstr] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr(ostr, "v_") != ostr) error->all(FLERR, "Invalid python command");
|
if (strstr(ostr, "v_") != ostr)
|
||||||
|
error->all(FLERR, Error::NOLASTLINE, "Invalid python output variable name {}", ostr);
|
||||||
pfuncs[ifunc].ovarname = utils::strdup(ostr + 2);
|
pfuncs[ifunc].ovarname = utils::strdup(ostr + 2);
|
||||||
|
|
||||||
return ifunc;
|
return ifunc;
|
||||||
@ -574,6 +710,7 @@ void PythonImpl::deallocate(int i)
|
|||||||
delete[] pfuncs[i].dvalue;
|
delete[] pfuncs[i].dvalue;
|
||||||
for (int j = 0; j < pfuncs[i].ninput; j++) delete[] pfuncs[i].svalue[j];
|
for (int j = 0; j < pfuncs[i].ninput; j++) delete[] pfuncs[i].svalue[j];
|
||||||
delete[] pfuncs[i].svalue;
|
delete[] pfuncs[i].svalue;
|
||||||
|
delete[] pfuncs[i].internal_var;
|
||||||
delete[] pfuncs[i].ovarname;
|
delete[] pfuncs[i].ovarname;
|
||||||
delete[] pfuncs[i].longstr;
|
delete[] pfuncs[i].longstr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,9 +25,10 @@ class PythonImpl : protected Pointers, public PythonInterface {
|
|||||||
PythonImpl(class LAMMPS *);
|
PythonImpl(class LAMMPS *);
|
||||||
~PythonImpl() override;
|
~PythonImpl() override;
|
||||||
void command(int, char **) override;
|
void command(int, char **) override;
|
||||||
void invoke_function(int, char *) override;
|
void invoke_function(int, char *, double *) override;
|
||||||
int find(const char *) override;
|
int find(const char *) override;
|
||||||
int variable_match(const char *, const char *, int) override;
|
int function_match(const char *, const char *, int, Error *) override;
|
||||||
|
int wrapper_match(const char *, const char *, int, int *, Error *) override;
|
||||||
char *long_string(int) override;
|
char *long_string(int) override;
|
||||||
int execute_string(char *) override;
|
int execute_string(char *) override;
|
||||||
int execute_file(char *) override;
|
int execute_file(char *) override;
|
||||||
@ -44,6 +45,7 @@ class PythonImpl : protected Pointers, public PythonInterface {
|
|||||||
int *ivalue;
|
int *ivalue;
|
||||||
double *dvalue;
|
double *dvalue;
|
||||||
char **svalue;
|
char **svalue;
|
||||||
|
int *internal_var; // stores per-arg index of internal variable
|
||||||
int otype;
|
int otype;
|
||||||
char *ovarname;
|
char *ovarname;
|
||||||
char *longstr;
|
char *longstr;
|
||||||
|
|||||||
@ -3109,7 +3109,7 @@ void FixBondReact::update_everything()
|
|||||||
update_num_mega++;
|
update_num_mega++;
|
||||||
}
|
}
|
||||||
MPI_Allreduce(MPI_IN_PLACE, &noccur[0], nreacts, MPI_INT, MPI_SUM, world);
|
MPI_Allreduce(MPI_IN_PLACE, &noccur[0], nreacts, MPI_INT, MPI_SUM, world);
|
||||||
reaction_count_total[rxnID] += noccur[rxnID];
|
for (rxnID = 0; rxnID < nreacts; rxnID++) reaction_count_total[rxnID] += noccur[rxnID];
|
||||||
} else if (pass == 1) {
|
} else if (pass == 1) {
|
||||||
for (int i = 0; i < global_megasize; i++) {
|
for (int i = 0; i < global_megasize; i++) {
|
||||||
rxnID = (int) global_mega_glove[0][i];
|
rxnID = (int) global_mega_glove[0][i];
|
||||||
|
|||||||
@ -108,7 +108,10 @@ ComputeAngleLocal::ComputeAngleLocal(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
|
|
||||||
if (tstr) {
|
if (tstr) {
|
||||||
tvar = input->variable->find(tstr);
|
tvar = input->variable->find(tstr);
|
||||||
if (tvar < 0) error->all(FLERR, "Variable name for compute angle/local does not exist");
|
if (tvar < 0) {
|
||||||
|
input->variable->internal_create(tstr,0.0);
|
||||||
|
tvar = input->variable->find(tstr);
|
||||||
|
}
|
||||||
if (!input->variable->internalstyle(tvar))
|
if (!input->variable->internalstyle(tvar))
|
||||||
error->all(FLERR, "Variable for compute angle/local is invalid style");
|
error->all(FLERR, "Variable for compute angle/local is invalid style");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,7 +154,10 @@ ComputeBondLocal::ComputeBondLocal(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
|
|
||||||
if (dstr) {
|
if (dstr) {
|
||||||
dvar = input->variable->find(dstr);
|
dvar = input->variable->find(dstr);
|
||||||
if (dvar < 0) error->all(FLERR, "Variable name for compute bond/local does not exist");
|
if (dvar < 0) {
|
||||||
|
input->variable->internal_create(dstr,0.0);
|
||||||
|
dvar = input->variable->find(dstr);
|
||||||
|
}
|
||||||
if (!input->variable->internalstyle(dvar))
|
if (!input->variable->internalstyle(dvar))
|
||||||
error->all(FLERR, "Variable for compute bond/local is invalid style");
|
error->all(FLERR, "Variable for compute bond/local is invalid style");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,7 +102,10 @@ ComputeDihedralLocal::ComputeDihedralLocal(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
|
|
||||||
if (pstr) {
|
if (pstr) {
|
||||||
pvar = input->variable->find(pstr);
|
pvar = input->variable->find(pstr);
|
||||||
if (pvar < 0) error->all(FLERR, "Variable name for compute dihedral/local does not exist");
|
if (pvar < 0) {
|
||||||
|
input->variable->internal_create(pstr,0.0);
|
||||||
|
pvar = input->variable->find(pstr);
|
||||||
|
}
|
||||||
if (!input->variable->internalstyle(pvar))
|
if (!input->variable->internalstyle(pvar))
|
||||||
error->all(FLERR, "Variable for compute dihedral/local is invalid style");
|
error->all(FLERR, "Variable for compute dihedral/local is invalid style");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -390,28 +390,23 @@ void CreateAtoms::command(int narg, char **arg)
|
|||||||
if (!input->variable->equalstyle(vvar))
|
if (!input->variable->equalstyle(vvar))
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", vstr);
|
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", vstr);
|
||||||
|
|
||||||
if (xstr) {
|
#define SETUP_XYZ_VAR(str,var) \
|
||||||
xvar = input->variable->find(xstr);
|
if (str) { \
|
||||||
if (xvar < 0)
|
var = input->variable->find(str); \
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", xstr);
|
if (var < 0) { \
|
||||||
if (!input->variable->internalstyle(xvar))
|
input->variable->internal_create(str, 0.0); \
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", xstr);
|
var = input->variable->find(str); \
|
||||||
}
|
} \
|
||||||
if (ystr) {
|
if (!input->variable->internalstyle(var)) \
|
||||||
yvar = input->variable->find(ystr);
|
error->all(FLERR, Error::NOLASTLINE, \
|
||||||
if (yvar < 0)
|
"Variable {} for create_atoms is invalid style", str); \
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", ystr);
|
|
||||||
if (!input->variable->internalstyle(yvar))
|
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", ystr);
|
|
||||||
}
|
|
||||||
if (zstr) {
|
|
||||||
zvar = input->variable->find(zstr);
|
|
||||||
if (zvar < 0)
|
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms does not exist", zstr);
|
|
||||||
if (!input->variable->internalstyle(zvar))
|
|
||||||
error->all(FLERR, Error::NOLASTLINE, "Variable {} for create_atoms is invalid style", zstr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SETUP_XYZ_VAR(xstr, xvar);
|
||||||
|
SETUP_XYZ_VAR(ystr, yvar);
|
||||||
|
SETUP_XYZ_VAR(zstr, zvar);
|
||||||
}
|
}
|
||||||
|
#undef SETUP_XYZ_VAR
|
||||||
|
|
||||||
// require non-none lattice be defined for BOX or REGION styles
|
// require non-none lattice be defined for BOX or REGION styles
|
||||||
|
|
||||||
|
|||||||
@ -868,19 +868,28 @@ void FixDeposit::options(int narg, char **arg)
|
|||||||
|
|
||||||
if (xstr) {
|
if (xstr) {
|
||||||
xvar = input->variable->find(xstr);
|
xvar = input->variable->find(xstr);
|
||||||
if (xvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", xstr);
|
if (xvar < 0) {
|
||||||
|
input->variable->internal_create(xstr,0.0);
|
||||||
|
xvar = input->variable->find(xstr);
|
||||||
|
}
|
||||||
if (!input->variable->internalstyle(xvar))
|
if (!input->variable->internalstyle(xvar))
|
||||||
error->all(FLERR, "Variable for fix deposit is invalid style");
|
error->all(FLERR, "Variable for fix deposit is invalid style");
|
||||||
}
|
}
|
||||||
if (ystr) {
|
if (ystr) {
|
||||||
yvar = input->variable->find(ystr);
|
yvar = input->variable->find(ystr);
|
||||||
if (yvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", ystr);
|
if (yvar < 0) {
|
||||||
|
input->variable->internal_create(ystr,0.0);
|
||||||
|
yvar = input->variable->find(ystr);
|
||||||
|
}
|
||||||
if (!input->variable->internalstyle(yvar))
|
if (!input->variable->internalstyle(yvar))
|
||||||
error->all(FLERR, "Variable for fix deposit is invalid style");
|
error->all(FLERR, "Variable for fix deposit is invalid style");
|
||||||
}
|
}
|
||||||
if (zstr) {
|
if (zstr) {
|
||||||
zvar = input->variable->find(zstr);
|
zvar = input->variable->find(zstr);
|
||||||
if (zvar < 0) error->all(FLERR, "Variable {} for fix deposit does not exist", zstr);
|
if (zvar < 0) {
|
||||||
|
input->variable->internal_create(zstr,0.0);
|
||||||
|
zvar = input->variable->find(zstr);
|
||||||
|
}
|
||||||
if (!input->variable->internalstyle(zvar))
|
if (!input->variable->internalstyle(zvar))
|
||||||
error->all(FLERR, "Variable for fix deposit is invalid style");
|
error->all(FLERR, "Variable for fix deposit is invalid style");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,9 +14,8 @@
|
|||||||
#include "lmppython.h"
|
#include "lmppython.h"
|
||||||
#if defined(LMP_PYTHON)
|
#if defined(LMP_PYTHON)
|
||||||
#include "python_impl.h"
|
#include "python_impl.h"
|
||||||
#else
|
|
||||||
#include "error.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ void Python::init()
|
|||||||
#if defined(LMP_PYTHON)
|
#if defined(LMP_PYTHON)
|
||||||
if (!impl) impl = new PythonImpl(lmp);
|
if (!impl) impl = new PythonImpl(lmp);
|
||||||
#else
|
#else
|
||||||
error->all(FLERR, "Python support missing! Compile with PYTHON package installed!");
|
error->all(FLERR, Error::NOLASTLINE, "Python support missing! Compile with PYTHON package installed!");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,10 +66,10 @@ void Python::command(int narg, char **arg)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
void Python::invoke_function(int ifunc, char *result)
|
void Python::invoke_function(int ifunc, char *result, double *dvalue)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
impl->invoke_function(ifunc, result);
|
impl->invoke_function(ifunc, result, dvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@ -83,10 +82,19 @@ int Python::find(const char *name)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
int Python::variable_match(const char *name, const char *varname, int numeric)
|
int Python::function_match(const char *name, const char *varname, int numeric, Error *errptr)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
return impl->variable_match(name, varname, numeric);
|
return impl->function_match(name, varname, numeric, errptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
int Python::wrapper_match(const char *name, const char *varname, int narg, int *argvars,
|
||||||
|
Error *errptr)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
return impl->wrapper_match(name, varname, narg, argvars, errptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|||||||
@ -22,9 +22,10 @@ class PythonInterface {
|
|||||||
public:
|
public:
|
||||||
virtual ~PythonInterface() noexcept(false) {}
|
virtual ~PythonInterface() noexcept(false) {}
|
||||||
virtual void command(int, char **) = 0;
|
virtual void command(int, char **) = 0;
|
||||||
virtual void invoke_function(int, char *) = 0;
|
virtual void invoke_function(int, char *, double *) = 0;
|
||||||
virtual int find(const char *) = 0;
|
virtual int find(const char *) = 0;
|
||||||
virtual int variable_match(const char *, const char *, int) = 0;
|
virtual int function_match(const char *, const char *, int, Error *) = 0;
|
||||||
|
virtual int wrapper_match(const char *, const char *, int, int *, Error *) = 0;
|
||||||
virtual char *long_string(int ifunc) = 0;
|
virtual char *long_string(int ifunc) = 0;
|
||||||
virtual int execute_string(char *) = 0;
|
virtual int execute_string(char *) = 0;
|
||||||
virtual int execute_file(char *) = 0;
|
virtual int execute_file(char *) = 0;
|
||||||
@ -37,9 +38,10 @@ class Python : protected Pointers {
|
|||||||
~Python() override;
|
~Python() override;
|
||||||
|
|
||||||
void command(int, char **);
|
void command(int, char **);
|
||||||
void invoke_function(int, char *);
|
void invoke_function(int, char *, double *);
|
||||||
int find(const char *);
|
int find(const char *);
|
||||||
int variable_match(const char *, const char *, int);
|
int function_match(const char *, const char *, int, Error *);
|
||||||
|
int wrapper_match(const char *, const char *, int, int *, Error *);
|
||||||
char *long_string(int ifunc);
|
char *long_string(int ifunc);
|
||||||
int execute_string(char *);
|
int execute_string(char *);
|
||||||
int execute_file(char *);
|
int execute_file(char *);
|
||||||
|
|||||||
180
src/variable.cpp
180
src/variable.cpp
@ -81,6 +81,7 @@ enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,MODULO,UNARY,
|
|||||||
RAMP,STAGGER,LOGFREQ,LOGFREQ2,LOGFREQ3,STRIDE,STRIDE2,
|
RAMP,STAGGER,LOGFREQ,LOGFREQ2,LOGFREQ3,STRIDE,STRIDE2,
|
||||||
VDISPLACE,SWIGGLE,CWIGGLE,SIGN,GMASK,RMASK,
|
VDISPLACE,SWIGGLE,CWIGGLE,SIGN,GMASK,RMASK,
|
||||||
GRMASK,IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,IS_FILE,EXTRACT_SETTING,
|
GRMASK,IS_ACTIVE,IS_DEFINED,IS_AVAILABLE,IS_FILE,EXTRACT_SETTING,
|
||||||
|
PYWRAPPER,
|
||||||
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY,BIGINTARRAY,VECTORARRAY};
|
VALUE,ATOMARRAY,TYPEARRAY,INTARRAY,BIGINTARRAY,VECTORARRAY};
|
||||||
|
|
||||||
// customize by adding a special function
|
// customize by adding a special function
|
||||||
@ -116,6 +117,7 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp)
|
|||||||
num = nullptr;
|
num = nullptr;
|
||||||
which = nullptr;
|
which = nullptr;
|
||||||
pad = nullptr;
|
pad = nullptr;
|
||||||
|
pyindex = nullptr;
|
||||||
reader = nullptr;
|
reader = nullptr;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
dvalue = nullptr;
|
dvalue = nullptr;
|
||||||
@ -162,6 +164,7 @@ Variable::~Variable()
|
|||||||
memory->destroy(num);
|
memory->destroy(num);
|
||||||
memory->destroy(which);
|
memory->destroy(which);
|
||||||
memory->destroy(pad);
|
memory->destroy(pad);
|
||||||
|
memory->destroy(pyindex);
|
||||||
memory->sfree(reader);
|
memory->sfree(reader);
|
||||||
memory->sfree(data);
|
memory->sfree(data);
|
||||||
memory->sfree(dvalue);
|
memory->sfree(dvalue);
|
||||||
@ -594,6 +597,7 @@ void Variable::set(int narg, char **arg)
|
|||||||
num[nvar] = 2;
|
num[nvar] = 2;
|
||||||
which[nvar] = 1;
|
which[nvar] = 1;
|
||||||
pad[nvar] = 0;
|
pad[nvar] = 0;
|
||||||
|
pyindex[nvar] = -1;
|
||||||
data[nvar] = new char *[num[nvar]];
|
data[nvar] = new char *[num[nvar]];
|
||||||
data[nvar][0] = utils::strdup(arg[2]);
|
data[nvar][0] = utils::strdup(arg[2]);
|
||||||
data[nvar][1] = new char[VALUELENGTH];
|
data[nvar][1] = new char[VALUELENGTH];
|
||||||
@ -956,13 +960,12 @@ void Variable::python_command(int narg, char **arg)
|
|||||||
|
|
||||||
int Variable::equalstyle(int ivar)
|
int Variable::equalstyle(int ivar)
|
||||||
{
|
{
|
||||||
if (style[ivar] == EQUAL || style[ivar] == TIMER ||
|
if (style[ivar] == EQUAL || style[ivar] == TIMER || style[ivar] == INTERNAL) return 1;
|
||||||
style[ivar] == INTERNAL) return 1;
|
|
||||||
if (style[ivar] == PYTHON) {
|
if (style[ivar] == PYTHON) {
|
||||||
int ifunc = python->variable_match(data[ivar][0],names[ivar],1);
|
pyindex[ivar] = python->function_match(data[ivar][0], names[ivar], 1, error);
|
||||||
if (ifunc < 0) return 0;
|
if (pyindex[ivar] >= 0) return 1;
|
||||||
else return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,7 +992,7 @@ int Variable::vectorstyle(int ivar)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
check if variable with name is PYTHON and matches funcname
|
check if variable with name is PYTHON style and matches funcname
|
||||||
called by Python class before it invokes a Python function
|
called by Python class before it invokes a Python function
|
||||||
return data storage so Python function can return a value for this variable
|
return data storage so Python function can return a value for this variable
|
||||||
return nullptr if not a match
|
return nullptr if not a match
|
||||||
@ -1006,7 +1009,7 @@ char *Variable::pythonstyle(char *name, char *funcname)
|
|||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
return 1 if variable is INTERNAL style, 0 if not
|
return 1 if variable is INTERNAL style, 0 if not
|
||||||
this is checked before call to set_internal() to assure it can be set
|
this is checked before call to internal_set() to ensure it can be set
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int Variable::internalstyle(int ivar)
|
int Variable::internalstyle(int ivar)
|
||||||
@ -1082,23 +1085,8 @@ char *Variable::retrieve(const char *name)
|
|||||||
str = data[ivar][1] = utils::strdup(result);
|
str = data[ivar][1] = utils::strdup(result);
|
||||||
|
|
||||||
} else if (style[ivar] == PYTHON) {
|
} else if (style[ivar] == PYTHON) {
|
||||||
int ifunc = python->variable_match(data[ivar][0],name,0);
|
int ifunc = python->function_match(data[ivar][0],name,0,error);
|
||||||
if (ifunc < 0) {
|
python->invoke_function(ifunc,data[ivar][1],nullptr);
|
||||||
if (ifunc == -1) {
|
|
||||||
error->all(FLERR, "Could not find Python function {} linked to variable {}",
|
|
||||||
data[ivar][0], name);
|
|
||||||
} else if (ifunc == -2) {
|
|
||||||
error->all(FLERR, "Python function {} for variable {} does not have a return value",
|
|
||||||
data[ivar][0], name);
|
|
||||||
} else if (ifunc == -3) {
|
|
||||||
error->all(FLERR,"Python variable {} does not match variable name registered with "
|
|
||||||
"Python function {}", name, data[ivar][0]);
|
|
||||||
} else {
|
|
||||||
error->all(FLERR, "Unknown error verifying function {} linked to python style variable {}",
|
|
||||||
data[ivar][0],name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
python->invoke_function(ifunc,data[ivar][1]);
|
|
||||||
str = data[ivar][1];
|
str = data[ivar][1];
|
||||||
|
|
||||||
// if Python func returns a string longer than VALUELENGTH
|
// if Python func returns a string longer than VALUELENGTH
|
||||||
@ -1157,17 +1145,7 @@ double Variable::compute_equal(int ivar)
|
|||||||
if (style[ivar] == EQUAL) value = evaluate(data[ivar][0],nullptr,ivar);
|
if (style[ivar] == EQUAL) value = evaluate(data[ivar][0],nullptr,ivar);
|
||||||
else if (style[ivar] == TIMER) value = dvalue[ivar];
|
else if (style[ivar] == TIMER) value = dvalue[ivar];
|
||||||
else if (style[ivar] == INTERNAL) value = dvalue[ivar];
|
else if (style[ivar] == INTERNAL) value = dvalue[ivar];
|
||||||
else if (style[ivar] == PYTHON) {
|
else if (style[ivar] == PYTHON) python->invoke_function(pyindex[ivar],nullptr,&value);
|
||||||
int ifunc = python->find(data[ivar][0]);
|
|
||||||
if (ifunc < 0)
|
|
||||||
print_var_error(FLERR,fmt::format("cannot find python function {}",data[ivar][0]),ivar);
|
|
||||||
python->invoke_function(ifunc,data[ivar][1]);
|
|
||||||
try {
|
|
||||||
value = std::stod(data[ivar][1]);
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
print_var_error(FLERR,"has an invalid value", ivar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// round to zero on underflow
|
// round to zero on underflow
|
||||||
if (fabs(value) < std::numeric_limits<double>::min()) value = 0.0;
|
if (fabs(value) < std::numeric_limits<double>::min()) value = 0.0;
|
||||||
@ -1334,6 +1312,30 @@ void Variable::internal_set(int ivar, double value)
|
|||||||
dvalue[ivar] = value;
|
dvalue[ivar] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
create an INTERNAL style variable with name, set to value
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void Variable::internal_create(char *name, double value)
|
||||||
|
{
|
||||||
|
if (find(name) >= 0)
|
||||||
|
error->all(FLERR,"Creation of internal-style variable {} which already exists", name);
|
||||||
|
|
||||||
|
if (nvar == maxvar) grow();
|
||||||
|
style[nvar] = INTERNAL;
|
||||||
|
num[nvar] = 1;
|
||||||
|
which[nvar] = 0;
|
||||||
|
pad[nvar] = 0;
|
||||||
|
data[nvar] = new char *[num[nvar]];
|
||||||
|
data[nvar][0] = new char[VALUELENGTH];
|
||||||
|
dvalue[nvar] = value;
|
||||||
|
|
||||||
|
if (!utils::is_id(name))
|
||||||
|
error->all(FLERR, "Variable name '{}' must have only letters, numbers, or underscores", name);
|
||||||
|
names[nvar] = utils::strdup(name);
|
||||||
|
nvar++;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
remove Nth variable from list and compact list
|
remove Nth variable from list and compact list
|
||||||
delete reader explicitly if it exists
|
delete reader explicitly if it exists
|
||||||
@ -1381,6 +1383,7 @@ void Variable::grow()
|
|||||||
memory->grow(num,maxvar,"var:num");
|
memory->grow(num,maxvar,"var:num");
|
||||||
memory->grow(which,maxvar,"var:which");
|
memory->grow(which,maxvar,"var:which");
|
||||||
memory->grow(pad,maxvar,"var:pad");
|
memory->grow(pad,maxvar,"var:pad");
|
||||||
|
memory->grow(pyindex,maxvar,"var:pyindex");
|
||||||
|
|
||||||
reader = (VarReader **)
|
reader = (VarReader **)
|
||||||
memory->srealloc(reader,maxvar*sizeof(VarReader *),"var:reader");
|
memory->srealloc(reader,maxvar*sizeof(VarReader *),"var:reader");
|
||||||
@ -1424,6 +1427,7 @@ void Variable::copy(int narg, char **from, char **to)
|
|||||||
sin(x),cos(x),tan(x),asin(x),atan2(y,x),...
|
sin(x),cos(x),tan(x),asin(x),atan2(y,x),...
|
||||||
group function = count(group), mass(group), xcm(group,x), ...
|
group function = count(group), mass(group), xcm(group,x), ...
|
||||||
special function = sum(x),min(x), ...
|
special function = sum(x),min(x), ...
|
||||||
|
python function wrapper = py_varname(x,y,z,...) (up to MAXFUNCARG)
|
||||||
atom value = x[i], y[i], vx[i], ...
|
atom value = x[i], y[i], vx[i], ...
|
||||||
atom vector = x, y, vx, ...
|
atom vector = x, y, vx, ...
|
||||||
custom atom property = i/d_name, i/d_name[i], i/d2_name[i], i/d2_name[i][j]
|
custom atom property = i/d_name, i/d_name[i], i/d2_name[i], i/d2_name[i][j]
|
||||||
@ -2361,13 +2365,14 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
// math/group/special/labelmap function or atom value/vector or constant or thermo keyword
|
// math/group/region/special/feature function or atom value/vector or constant or thermo keyword
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// ----------------
|
// ----------------
|
||||||
// math or group or special function
|
// math or group/region or special or feature function
|
||||||
|
// math_function() includes Python function wrapper
|
||||||
// ----------------
|
// ----------------
|
||||||
|
|
||||||
if (str[i] == '(') {
|
if (str[i] == '(') {
|
||||||
@ -2625,7 +2630,8 @@ double Variable::evaluate(char *str, Tree **tree, int ivar)
|
|||||||
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),ternary(x,y,z),
|
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),ternary(x,y,z),
|
||||||
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
|
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
|
||||||
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),swiggle(x,y,z),
|
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),swiggle(x,y,z),
|
||||||
cwiggle(x,y,z),sign(x),gmask(x),rmask(x),grmask(x,y)
|
cwiggle(x,y,z),sign(x),py_varname(x,y,z,...),
|
||||||
|
gmask(x),rmask(x),grmask(x,y)
|
||||||
---------------------------------------------------------------------- */
|
---------------------------------------------------------------------- */
|
||||||
|
|
||||||
double Variable::collapse_tree(Tree *tree)
|
double Variable::collapse_tree(Tree *tree)
|
||||||
@ -3183,6 +3189,30 @@ double Variable::collapse_tree(Tree *tree)
|
|||||||
return tree->value;
|
return tree->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tree->type == PYWRAPPER) {
|
||||||
|
int narg = tree->argcount;
|
||||||
|
int *argvars = tree->argvars;
|
||||||
|
double arg;
|
||||||
|
for (int iarg = 0; iarg < narg; iarg++) {
|
||||||
|
if (iarg == 0) arg = collapse_tree(tree->first);
|
||||||
|
else if (iarg == 1) arg = collapse_tree(tree->second);
|
||||||
|
else arg = collapse_tree(tree->extra[iarg-2]);
|
||||||
|
internal_set(argvars[iarg],arg);
|
||||||
|
}
|
||||||
|
for (int iarg = 0; iarg < narg; iarg++) {
|
||||||
|
if (iarg == 0) {
|
||||||
|
if (tree->first->type != VALUE) return 0.0;
|
||||||
|
} else if (iarg == 1) {
|
||||||
|
if (tree->second->type != VALUE) return 0.0;
|
||||||
|
} else {
|
||||||
|
if (tree->extra[iarg-2]->type != VALUE) return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree->type = VALUE;
|
||||||
|
tree->value = compute_equal(tree->pyvar);
|
||||||
|
return tree->value;
|
||||||
|
}
|
||||||
|
|
||||||
// mask functions do not become a single collapsed value
|
// mask functions do not become a single collapsed value
|
||||||
|
|
||||||
if (tree->type == GMASK) return 0.0;
|
if (tree->type == GMASK) return 0.0;
|
||||||
@ -3196,12 +3226,14 @@ double Variable::collapse_tree(Tree *tree)
|
|||||||
evaluate an atom-style or vector-style variable parse tree
|
evaluate an atom-style or vector-style variable parse tree
|
||||||
index I = atom I or vector index I
|
index I = atom I or vector index I
|
||||||
tree was created by one-time parsing of formula string via evaluate()
|
tree was created by one-time parsing of formula string via evaluate()
|
||||||
|
followed by collapse_tree() operation to streamline tree as much as possible
|
||||||
customize by adding a function:
|
customize by adding a function:
|
||||||
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
|
sqrt(),exp(),ln(),log(),sin(),cos(),tan(),asin(),acos(),atan(),
|
||||||
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),ternary(x,y,z),
|
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),ternary(x,y,z),
|
||||||
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
|
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
|
||||||
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),
|
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),
|
||||||
swiggle(x,y,z),cwiggle(x,y,z),sign(x),gmask(x),rmask(x),grmask(x,y)
|
swiggle(x,y,z),cwiggle(x,y,z),sign(x),py_varname(x,y,z,...),
|
||||||
|
gmask(x),rmask(x),grmask(x,y)
|
||||||
---------------------------------------------------------------------- */
|
---------------------------------------------------------------------- */
|
||||||
|
|
||||||
double Variable::eval_tree(Tree *tree, int i)
|
double Variable::eval_tree(Tree *tree, int i)
|
||||||
@ -3518,7 +3550,19 @@ double Variable::eval_tree(Tree *tree, int i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tree->type == SIGN)
|
if (tree->type == SIGN)
|
||||||
return (eval_tree(tree->first,i) >= 0.0) ? 1.0 : -1.0; // sign(eval_tree(tree->first,i));
|
return (eval_tree(tree->first,i) >= 0.0) ? 1.0 : -1.0; // sign(eval_tree(tree->first,i));
|
||||||
|
|
||||||
|
if (tree->type == PYWRAPPER) {
|
||||||
|
int narg = tree->argcount;
|
||||||
|
for (int iarg = 0; iarg < narg; iarg++) {
|
||||||
|
if (iarg == 0) arg = eval_tree(tree->first,i);
|
||||||
|
else if (iarg == 1) arg = eval_tree(tree->second,i);
|
||||||
|
else arg = eval_tree(tree->extra[iarg-2],i);
|
||||||
|
internal_set(tree->argvars[iarg],arg);
|
||||||
|
}
|
||||||
|
arg = compute_equal(tree->pyvar);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
if (tree->type == GMASK) {
|
if (tree->type == GMASK) {
|
||||||
if (atom->mask[i] & tree->ivalue) return 1.0;
|
if (atom->mask[i] & tree->ivalue) return 1.0;
|
||||||
@ -3583,6 +3627,7 @@ void Variable::free_tree(Tree *tree)
|
|||||||
for (int i = 0; i < tree->nextra; i++) free_tree(tree->extra[i]);
|
for (int i = 0; i < tree->nextra; i++) free_tree(tree->extra[i]);
|
||||||
delete[] tree->extra;
|
delete[] tree->extra;
|
||||||
}
|
}
|
||||||
|
if (tree->argvars) delete[] tree->argvars;
|
||||||
|
|
||||||
if (tree->selfalloc) memory->destroy(tree->array);
|
if (tree->selfalloc) memory->destroy(tree->array);
|
||||||
delete tree;
|
delete tree;
|
||||||
@ -3685,7 +3730,7 @@ tagint Variable::int_between_brackets(char *&ptr, int varallow)
|
|||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
process a math function in formula
|
process a math function in formula
|
||||||
push result onto tree or arg stack
|
push result onto tree or arg stack
|
||||||
word = math function
|
word = math function name
|
||||||
contents = str between parentheses with comma-separated args
|
contents = str between parentheses with comma-separated args
|
||||||
return 0 if not a match, 1 if successfully processed
|
return 0 if not a match, 1 if successfully processed
|
||||||
customize by adding a math function:
|
customize by adding a math function:
|
||||||
@ -3693,7 +3738,7 @@ tagint Variable::int_between_brackets(char *&ptr, int varallow)
|
|||||||
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),ternary(),
|
atan2(y,x),random(x,y,z),normal(x,y,z),ceil(),floor(),round(),ternary(),
|
||||||
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
|
ramp(x,y),stagger(x,y),logfreq(x,y,z),logfreq2(x,y,z),
|
||||||
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),
|
logfreq3(x,y,z),stride(x,y,z),stride2(x,y,z,a,b,c),vdisplace(x,y),
|
||||||
swiggle(x,y,z),cwiggle(x,y,z),sign(x)
|
swiggle(x,y,z),cwiggle(x,y,z),sign(x),py_varname(x,y,z,...)
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int Variable::math_function(char *word, char *contents, Tree **tree, Tree **treestack,
|
int Variable::math_function(char *word, char *contents, Tree **tree, Tree **treestack,
|
||||||
@ -3711,7 +3756,8 @@ int Variable::math_function(char *word, char *contents, Tree **tree, Tree **tree
|
|||||||
strcmp(word,"logfreq") != 0 && strcmp(word,"logfreq2") != 0 &&
|
strcmp(word,"logfreq") != 0 && strcmp(word,"logfreq2") != 0 &&
|
||||||
strcmp(word,"logfreq3") != 0 && strcmp(word,"stride") != 0 &&
|
strcmp(word,"logfreq3") != 0 && strcmp(word,"stride") != 0 &&
|
||||||
strcmp(word,"stride2") != 0 && strcmp(word,"vdisplace") != 0 &&
|
strcmp(word,"stride2") != 0 && strcmp(word,"vdisplace") != 0 &&
|
||||||
strcmp(word,"swiggle") != 0 && strcmp(word,"cwiggle") != 0 && strcmp(word,"sign") != 0)
|
strcmp(word,"swiggle") != 0 && strcmp(word,"cwiggle") != 0 && strcmp(word,"sign") != 0 &&
|
||||||
|
strstr(word,"py_") != word)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// parse contents for comma-separated args
|
// parse contents for comma-separated args
|
||||||
@ -4106,11 +4152,51 @@ int Variable::math_function(char *word, char *contents, Tree **tree, Tree **tree
|
|||||||
double value = value1 + value2*(1.0-cos(omega*delta*update->dt));
|
double value = value1 + value2*(1.0-cos(omega*delta*update->dt));
|
||||||
argstack[nargstack++] = value;
|
argstack[nargstack++] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (strcmp(word,"sign") == 0) {
|
} else if (strcmp(word,"sign") == 0) {
|
||||||
if (narg != 1)
|
if (narg != 1)
|
||||||
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
|
print_var_error(FLERR,"Invalid math function in variable formula",ivar);
|
||||||
if (tree) newtree->type = SIGN;
|
if (tree) newtree->type = SIGN;
|
||||||
else argstack[nargstack++] = (value1 >= 0.0) ? 1.0 : -1.0; // sign(value1);
|
else argstack[nargstack++] = (value1 >= 0.0) ? 1.0 : -1.0; // sign(value1);
|
||||||
|
|
||||||
|
// Python wrapper function tied to python-style variable
|
||||||
|
// text following py_ = python-style variable name tied to Python function
|
||||||
|
// narg arguments are tied to internal variables defined by python command
|
||||||
|
|
||||||
|
} else if (strstr(word,"py_") == word) {
|
||||||
|
|
||||||
|
// pyvar = index of python-style variable which invokes Python function
|
||||||
|
|
||||||
|
int pyvar = find(&word[3]);
|
||||||
|
if (style[pyvar] != PYTHON)
|
||||||
|
print_var_error(FLERR,"Invalid python function variable name",ivar);
|
||||||
|
|
||||||
|
// check that wrapper matches Python function
|
||||||
|
// jvars = returned indices of narg internal variables used by Python function
|
||||||
|
|
||||||
|
int *jvars = new int[narg];
|
||||||
|
pyindex[pyvar] = python->wrapper_match(data[pyvar][0],names[pyvar],narg,jvars,error);
|
||||||
|
|
||||||
|
// if tree: store python variable and arg info in tree for later eval
|
||||||
|
// else: one-time eval of python-coded function now via python variable
|
||||||
|
|
||||||
|
if (tree) {
|
||||||
|
newtree->type = PYWRAPPER;
|
||||||
|
newtree->pyvar = pyvar;
|
||||||
|
newtree->argcount = narg;
|
||||||
|
newtree->argvars = new int[narg];
|
||||||
|
for (int iarg = 0; iarg < narg; iarg++)
|
||||||
|
newtree->argvars[iarg] = jvars[iarg];
|
||||||
|
} else {
|
||||||
|
for (int iarg = 0; iarg < narg; iarg++) {
|
||||||
|
if (iarg == 0) internal_set(jvars[iarg],value1);
|
||||||
|
else if (iarg == 1) internal_set(jvars[iarg],value2);
|
||||||
|
else internal_set(jvars[iarg],values[iarg-2]);
|
||||||
|
}
|
||||||
|
argstack[nargstack++] = compute_equal(pyvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] jvars;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete stored args
|
// delete stored args
|
||||||
@ -4377,7 +4463,7 @@ Region *Variable::region_function(char *id, int ivar)
|
|||||||
customize by adding a special function:
|
customize by adding a special function:
|
||||||
sum(x),min(x),max(x),ave(x),trap(x),slope(x),
|
sum(x),min(x),max(x),ave(x),trap(x),slope(x),
|
||||||
gmask(x),rmask(x),grmask(x,y),next(x),is_file(x),is_os(x),
|
gmask(x),rmask(x),grmask(x,y),next(x),is_file(x),is_os(x),
|
||||||
extract_setting(x),label2type(x,y),is_tpelabel(x,y)
|
extract_setting(x),label2type(x,y),is_typelabel(x,y)
|
||||||
is_timeout()
|
is_timeout()
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
@ -5296,7 +5382,11 @@ void Variable::print_var_error(const std::string &srcfile, const int lineno,
|
|||||||
|
|
||||||
void Variable::print_tree(Tree *tree, int level)
|
void Variable::print_tree(Tree *tree, int level)
|
||||||
{
|
{
|
||||||
printf("TREE %d: %d %g\n",level,tree->type,tree->value);
|
if (tree->type == VALUE) {
|
||||||
|
printf("TREE %d: %d %g\n",level,tree->type,tree->value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("TREE %d: %d\n",level,tree->type);
|
||||||
if (tree->first) print_tree(tree->first,level+1);
|
if (tree->first) print_tree(tree->first,level+1);
|
||||||
if (tree->second) print_tree(tree->second,level+1);
|
if (tree->second) print_tree(tree->second,level+1);
|
||||||
if (tree->nextra)
|
if (tree->nextra)
|
||||||
|
|||||||
@ -49,6 +49,7 @@ class Variable : protected Pointers {
|
|||||||
void compute_atom(int, int, double *, int, int);
|
void compute_atom(int, int, double *, int, int);
|
||||||
int compute_vector(int, double **);
|
int compute_vector(int, double **);
|
||||||
void internal_set(int, double);
|
void internal_set(int, double);
|
||||||
|
void internal_create(char *, double);
|
||||||
|
|
||||||
tagint int_between_brackets(char *&, int);
|
tagint int_between_brackets(char *&, int);
|
||||||
double evaluate_boolean(char *);
|
double evaluate_boolean(char *);
|
||||||
@ -87,6 +88,7 @@ class Variable : protected Pointers {
|
|||||||
int *num; // # of values for each variable
|
int *num; // # of values for each variable
|
||||||
int *which; // next available value for each variable
|
int *which; // next available value for each variable
|
||||||
int *pad; // 1 = pad loop/uloop variables with 0s, 0 = no pad
|
int *pad; // 1 = pad loop/uloop variables with 0s, 0 = no pad
|
||||||
|
int *pyindex; // indices to Python funcs for python-style vars
|
||||||
class VarReader **reader; // variable that reads from file
|
class VarReader **reader; // variable that reads from file
|
||||||
char ***data; // str value of each variable's values
|
char ***data; // str value of each variable's values
|
||||||
double *dvalue; // single numeric value for internal variables
|
double *dvalue; // single numeric value for internal variables
|
||||||
@ -123,9 +125,13 @@ class Variable : protected Pointers {
|
|||||||
Tree *first, *second; // ptrs further down tree for first 2 args
|
Tree *first, *second; // ptrs further down tree for first 2 args
|
||||||
Tree **extra; // ptrs further down tree for nextra args
|
Tree **extra; // ptrs further down tree for nextra args
|
||||||
|
|
||||||
|
int pyvar; // index of Python variable invoked as py_name()
|
||||||
|
int argcount; // # of args to associated Python function
|
||||||
|
int *argvars; // indices of internal variables for each arg
|
||||||
|
|
||||||
Tree() :
|
Tree() :
|
||||||
array(nullptr), iarray(nullptr), barray(nullptr), selfalloc(0), ivalue(0), nextra(0),
|
array(nullptr), iarray(nullptr), barray(nullptr), selfalloc(0), ivalue(0), nextra(0),
|
||||||
region(nullptr), first(nullptr), second(nullptr), extra(nullptr)
|
region(nullptr), first(nullptr), second(nullptr), extra(nullptr), argvars(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -85,7 +85,7 @@ void WriteDump::command(int narg, char **arg)
|
|||||||
if (strcmp(arg[1], "image") == 0) (dynamic_cast<DumpImage *>(dump))->multifile_override = 1;
|
if (strcmp(arg[1], "image") == 0) (dynamic_cast<DumpImage *>(dump))->multifile_override = 1;
|
||||||
if (strcmp(arg[1], "cfg") == 0) (dynamic_cast<DumpCFG *>(dump))->multifile_override = 1;
|
if (strcmp(arg[1], "cfg") == 0) (dynamic_cast<DumpCFG *>(dump))->multifile_override = 1;
|
||||||
if ((update->first_update == 0) && (comm->me == 0) && (noinitwarn == 0))
|
if ((update->first_update == 0) && (comm->me == 0) && (noinitwarn == 0))
|
||||||
error->warning(FLERR, "Calling write_dump before a full system init.");
|
error->warning(FLERR, "Calling write_dump before a full system init");
|
||||||
|
|
||||||
dump->init();
|
dump->init();
|
||||||
dump->write();
|
dump->write();
|
||||||
|
|||||||
Reference in New Issue
Block a user