updated doc pages and code
This commit is contained in:
@ -10,43 +10,45 @@ Syntax
|
||||
|
||||
python mode keyword args ...
|
||||
|
||||
* mode = *source* or name of Python function
|
||||
* mode = *source* or *name* of Python function
|
||||
|
||||
if mode is *source*:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
keyword = *here* or name of a *Python file*
|
||||
*here* arg = inline
|
||||
inline = one or more lines of Python code which defines func
|
||||
must be a single argument, typically enclosed between triple quotes
|
||||
*here* arg = one or more lines of Python code
|
||||
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
|
||||
|
||||
* 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::
|
||||
|
||||
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*
|
||||
*invoke* arg = none = invoke the previously defined Python function
|
||||
*invoke* arg = none = invoke the previously-defined Python function
|
||||
*input* args = N i1 i2 ... iN
|
||||
N = # of inputs to function
|
||||
i1,...,iN = value, SELF, or LAMMPS variable name
|
||||
value = integer number, floating point number, or string
|
||||
SELF = reference to LAMMPS itself which can be accessed by Python function
|
||||
variable = v_name, where name = name of LAMMPS variable, e.g. v_abc
|
||||
SELF = reference to LAMMPS itself which can then be accessed by Python function
|
||||
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
|
||||
varReturn = v_name = LAMMPS variable name which the return value of the Python function will be assigned to
|
||||
*format* arg = fstring with M characters
|
||||
M = N if no return value, where N = # of inputs
|
||||
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
|
||||
'i' = integer, 'f' = floating point, 's' = string, 'p' = SELF
|
||||
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
|
||||
*length* arg = Nlen
|
||||
Nlen = max length of string returned from Python function
|
||||
*file* arg = filename
|
||||
filename = file of Python code, which defines func
|
||||
filename = file of Python code, which defines the Python function
|
||||
*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
|
||||
*exists* arg = none = Python code has been loaded by previous python command
|
||||
|
||||
@ -87,37 +89,43 @@ Examples
|
||||
Description
|
||||
"""""""""""
|
||||
|
||||
The *python* command allows interfacing LAMMPS with an embedded Python
|
||||
interpreter and enables either executing arbitrary python code in that
|
||||
interpreter, registering a Python function for future execution (as a
|
||||
python style variable, from a fix interfaced with python, or for direct
|
||||
invocation), or invoking such a previously registered function.
|
||||
The *python* command interfaces LAMMPS with an embedded Python
|
||||
interpreter and enables executing arbitrary python code in that
|
||||
interpreter. This can be done immediately, by using *mode* =
|
||||
*source*. Or execution can be deferred, by registering a Python
|
||||
function for later execution, by using *mode* = *name* of a Python
|
||||
function.
|
||||
|
||||
Arguments, including LAMMPS variables, can be passed to the function
|
||||
from the LAMMPS input script and a value returned by the Python function
|
||||
assigned to a LAMMPS variable. 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.
|
||||
Later execution can be triggered in one of two ways. One is to use
|
||||
the python command again with its *invoke* keyword. The other is to
|
||||
trigger the evaluation of a python-style, equal-style, or atom-style
|
||||
variable. A python-style variable invokes its associated Python
|
||||
function; its return value becomes the value of the python-style
|
||||
variable. Equal- and atom-style variables can use a Python function
|
||||
wrapper in their formulas which encodes the Python function name, and
|
||||
specifies arguments to pass to the function.
|
||||
|
||||
Note python-style, equal-style, and atom-style variables can be used
|
||||
in many different ways within LAMMPS. They can be evaulated 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
|
||||
which links to the Python library so that the Python interpreter is
|
||||
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
|
||||
:doc:`Use Python with LAMMPS <Python_head>` section of the
|
||||
documentation. There also is an ``examples/python`` directory which
|
||||
@ -125,25 +133,31 @@ illustrates use of the python command.
|
||||
|
||||
----------
|
||||
|
||||
The first argument of the *python* command is either the *source*
|
||||
keyword or the name of a Python function. This defines the mode
|
||||
of the python command.
|
||||
The first argument is the *mode* setting, which is either *source* or
|
||||
the *name* of a Python function.
|
||||
|
||||
.. versionchanged:: 22Dec2022
|
||||
|
||||
If the *source* keyword is used, it is followed by either a file name or
|
||||
the *here* keyword. No other keywords can be used. The *here* keyword
|
||||
is followed by a string with python commands, either on a single line
|
||||
enclosed in quotes, or as multiple lines enclosed in triple quotes.
|
||||
These Python commands will be passed to the python interpreter and
|
||||
executed immediately without registering a Python function for future
|
||||
execution. The code will be loaded into and run in the "main" module of
|
||||
the Python interpreter. This allows running arbitrary Python code at
|
||||
any time while processing the LAMMPS input file. This can be used to
|
||||
pre-load Python modules, initialize global variables, define functions
|
||||
or classes, or perform operations using the python programming language.
|
||||
The Python code will be executed in parallel on all MPI processes. No
|
||||
arguments can be passed.
|
||||
If *source* is used, it is followed by either the *here* keyword or a
|
||||
file name containing Python code. The *here* keyword is followed by a
|
||||
string containing python commands, either on a single line enclosed in
|
||||
quotes, or as multiple lines enclosed in triple quotes. In either
|
||||
case, the in-line code or file contents are passed to the python
|
||||
interpreter and executed immediately. The code will be loaded into
|
||||
and run in the "main" module of the Python interpreter. This allows
|
||||
running arbitrary Python code at any time while processing the SPARTA
|
||||
input file. This can be used to pre-load Python modules, initialize
|
||||
global variables, define functions or classes, or perform operations
|
||||
using the Python programming language. The Python code will be
|
||||
executed in parallel on all the MPI processes being used to run
|
||||
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
|
||||
that will be registered with LAMMPS for future execution. The function
|
||||
@ -154,40 +168,79 @@ If the *invoke* keyword is used, no other keywords can be used, and a
|
||||
previous *python* command must have registered the Python function
|
||||
referenced by this command. This invokes the Python function with the
|
||||
previously defined arguments and the return value is processed as
|
||||
explained below. You can invoke the function as many times as you wish
|
||||
in your input script.
|
||||
explained below. You can invoke a registered function as many times
|
||||
as you wish in your input script.
|
||||
|
||||
NOTE: As indicated with a NOTE in python_impl.cpp, I don't think there
|
||||
is any access to a value returned by invoking a Py function in this way.
|
||||
If that is correct, I think this should be clarified in the doc page,
|
||||
with a better explanation of the utility of using the *invoke* keyword.
|
||||
|
||||
The *input* keyword defines how many arguments *N* the Python function
|
||||
expects. If it takes no arguments, then the *input* keyword should not
|
||||
be used. Each argument can be specified directly as a value, e.g. '6'
|
||||
or '3.14159' or 'abc' (a string of characters). The type of each
|
||||
argument is specified by the *format* keyword as explained below, so
|
||||
that Python will know how to interpret the value. If the word SELF is
|
||||
used for an argument it has a special meaning. A pointer is passed to
|
||||
the Python function which it can convert into a reference to LAMMPS
|
||||
expects. If it takes no arguments, then the *input* keyword should
|
||||
not be used. Each argument can be specified directly as a value,
|
||||
e.g. '6' or '3.14159' or 'abc' (a string of characters). The type of
|
||||
each argument is specified by the *format* keyword as explained below,
|
||||
so that Python will know how to interpret the value. If the word SELF
|
||||
is used for an argument it has a special meaning. A pointer is passed
|
||||
to the Python function which it can convert into a reference to LAMMPS
|
||||
itself using the :doc:`LAMMPS Python module <Python_module>`. This
|
||||
enables the function to call back to LAMMPS through its library
|
||||
interface as explained below. This allows the Python function to 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
|
||||
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,
|
||||
as defined by the :doc:`variable <variable>` command. The *format*
|
||||
keyword must be used to set the type of data that is passed to Python.
|
||||
interface as explained below. This allows the Python function to
|
||||
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 *input* argument, specified
|
||||
as v_name, where "name" is the name of the variable defined in the
|
||||
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
|
||||
evaluated and its value is passed to the Python function.
|
||||
evaluated and its value is passed as an argument to the Python
|
||||
function.
|
||||
|
||||
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 or
|
||||
atom-style variable triggers the invocation of the Python function
|
||||
defined by this command, by including a Python function wrapper in its
|
||||
formula, with one or more arguments also included in the formula.
|
||||
|
||||
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 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;
|
||||
this 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).
|
||||
|
||||
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.
|
||||
|
||||
The *return* keyword is only needed if the Python function returns a
|
||||
value. The specified *varReturn* must be of the form v_name, where
|
||||
"name" is the name of a python-style LAMMPS variable, defined by the
|
||||
value. The specified *varReturn* is of the form v_name, where "name"
|
||||
is the name of a python-style LAMMPS variable, defined by the
|
||||
:doc:`variable <variable>` command. The Python function can return a
|
||||
numeric or string value, as specified by the *format* keyword.
|
||||
|
||||
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
|
||||
the *python* command. For example these two commands would be
|
||||
consistent:
|
||||
----------
|
||||
|
||||
As explained on the :doc:`variable <variable>` doc page, the
|
||||
definition of a python-style variable associates a Python function
|
||||
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
|
||||
|
||||
@ -196,43 +249,43 @@ consistent:
|
||||
|
||||
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
|
||||
the first time. Afterwards, the variable 'foo' is associated with
|
||||
the Python function 'myMultiply'.
|
||||
the first time.
|
||||
|
||||
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
|
||||
number of inputs and outputs. The order of characters corresponds to
|
||||
the N inputs, followed by the return value (if it exists). Each
|
||||
character must be one of the following: "i" for integer, "f" for
|
||||
floating point, "s" for string, or "p" for SELF. Each character defines
|
||||
the type of the corresponding input or output value of the Python
|
||||
function and affects the type conversion that is performed internally as
|
||||
data is passed back and forth between LAMMPS and Python. Note that it
|
||||
is permissible to use a :doc:`python-style variable <variable>` in a
|
||||
LAMMPS command that allows for an equal-style variable as an argument,
|
||||
but only if the output of the Python function is flagged as a numeric
|
||||
value ("i" or "f") via the *format* keyword.
|
||||
floating point, "s" for string, or "p" for SELF. Each character
|
||||
defines the type of the corresponding input or output value of the
|
||||
Python function and affects the type conversion that is performed
|
||||
internally as data is passed back and forth between LAMMPS and Python.
|
||||
Note that it is permissible to use a :doc:`python-style variable
|
||||
<variable>` in a LAMMPS command that allows for an equal-style
|
||||
variable as an argument, but only if the output of the Python function
|
||||
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
|
||||
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
|
||||
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
|
||||
include the string terminator). If the Python function generates a
|
||||
value set to a larger number. LAMMPS will then allocate Nlen+1 space
|
||||
to include the string terminator. If the Python function generates a
|
||||
string longer than the default 63 or the specified *Nlen*, it will be
|
||||
truncated.
|
||||
|
||||
----------
|
||||
|
||||
Either the *file*, *here*, or *exists* keyword must be used, but only
|
||||
one of them. These keywords specify what Python code to load into the
|
||||
Python interpreter. The *file* keyword gives the name of a file
|
||||
containing Python code, which should end with a ".py" suffix. The code
|
||||
will be immediately loaded into and run in the "main" module of the
|
||||
Python interpreter. The Python code will be executed in parallel on all
|
||||
MPI processes. Note that Python code which contains a function
|
||||
definition does not "execute" the function when it is run; it simply
|
||||
defines the function so that it can be invoked later.
|
||||
As noted above, either the *invoke*, *file*, *here*, or *exists*
|
||||
keyword must be used, but only one of them. These keywords specify
|
||||
what Python code to load into the Python interpreter. The *file*
|
||||
keyword gives the name of a file containing Python code, which should
|
||||
end with a ".py" suffix. The code will be immediately loaded into and
|
||||
run in the "main" module of the Python interpreter. The Python code
|
||||
will be executed in parallel on all MPI processes. Note that Python
|
||||
code which contains a function definition does not "execute" the
|
||||
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
|
||||
follows as a single argument to the *here* keyword. This can be done
|
||||
@ -243,15 +296,18 @@ proper indentation, blank lines, and comments, as desired. See the
|
||||
how triple quotes can be used as part of input script syntax.
|
||||
|
||||
The *exists* keyword takes no argument. It means that Python code
|
||||
containing the required Python function with the given name has already
|
||||
been executed, for example by a *python source* command or in the same
|
||||
file that was used previously with the *file* keyword.
|
||||
containing the required Python function with the given name has
|
||||
already been executed, for example by a *python source* command or in
|
||||
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
|
||||
with the specified function name. To operate properly when later
|
||||
invoked, the function code must match the *input* and *return* and
|
||||
*format* keywords specified by the python command. Otherwise Python
|
||||
will generate an error.
|
||||
Note that the Python code that is loaded and run by the *file* or
|
||||
*here* keyword must contain a function with the specified function
|
||||
name. To operate properly when later invoked, the function code must
|
||||
match the *input* and *return* and *format* keywords specified by the
|
||||
python command. Otherwise Python will generate an error.
|
||||
|
||||
----------
|
||||
|
||||
@ -308,13 +364,13 @@ previous value is simply returned, without re-computing it. The
|
||||
"global" statement inside the Python function allows it to overwrite the
|
||||
global variables from within the local context of the function.
|
||||
|
||||
Note that if you load Python code multiple times (via multiple python
|
||||
commands), you can overwrite previously loaded variables and functions
|
||||
if you are not careful. E.g. if the code above were loaded twice, the
|
||||
global variables would be re-initialized, which might not be what you
|
||||
want. Likewise, if a function with the same name exists in two chunks
|
||||
of Python code you load, the function loaded second will override the
|
||||
function loaded first.
|
||||
Also note that if you load Python code multiple times (via multiple
|
||||
python commands), you can overwrite previously loaded variables and
|
||||
functions if you are not careful. E.g. if the code above were loaded
|
||||
twice, the global variables would be re-initialized, which might not
|
||||
be what you want. Likewise, if a function with the same name exists
|
||||
in two chunks of Python code you load, the function loaded second will
|
||||
override the function loaded first.
|
||||
|
||||
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
|
||||
@ -325,15 +381,16 @@ This implies three important things.
|
||||
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,
|
||||
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
|
||||
the LAMMPS Python module into the embedded Python interpreter, it is
|
||||
possible to pass the pointer to the current LAMMPS class instance and
|
||||
via the Python interface to the LAMMPS library interface, it is possible
|
||||
to determine the MPI rank of the current process and thus adapt the
|
||||
Python code so that output will only appear on MPI rank 0. The
|
||||
following LAMMPS input demonstrates how this could be done. The text
|
||||
'Hello, LAMMPS!' should be printed only once, even when running LAMMPS
|
||||
in parallel.
|
||||
time, the P copies of the output may be mixed together.
|
||||
|
||||
It is possible to avoid this issue, by passing the pointer to the
|
||||
current LAMMPS class instance to the Python function via the {input}
|
||||
SELF argument described above. The Python function can then use the
|
||||
Python interface to the LAMMPS library interface, and determine the
|
||||
MPI rank of the current process. The Python code can then ensure
|
||||
output will only appear on MPI rank 0. The following LAMMPS input
|
||||
demonstrates how this could be done. The text 'Hello, LAMPS!' should
|
||||
be printed only once, even when running LAMMPS in parallel.
|
||||
|
||||
.. code-block:: LAMMPS
|
||||
|
||||
@ -348,13 +405,13 @@ in parallel.
|
||||
|
||||
python python_hello invoke
|
||||
|
||||
If your Python code loads Python modules that are not pre-loaded by the
|
||||
Python library, then it will load the module from disk. This may be a
|
||||
bottleneck if 1000s of processors try to load a module at the same time.
|
||||
On some large supercomputers, loading of modules from disk by Python may
|
||||
be disabled. In this case you would need to pre-build a Python library
|
||||
that has the required modules pre-loaded and link LAMMPS with that
|
||||
library.
|
||||
Second, if your Python code loads Python modules that are not
|
||||
pre-loaded by the Python library, then it will load the module from
|
||||
disk. This may be a bottleneck if 1000s of processors try to load a
|
||||
module at the same time. On some large supercomputers, loading of
|
||||
modules from disk by Python may be disabled. In this case you would
|
||||
need to pre-build a Python library that has the required modules
|
||||
pre-loaded and link LAMMPS with that library.
|
||||
|
||||
Third, if your Python code calls back to LAMMPS (discussed in the
|
||||
next section) and causes LAMMPS to perform an MPI operation requires
|
||||
@ -365,10 +422,10 @@ LAMMPS. Otherwise the code may hang.
|
||||
|
||||
----------
|
||||
|
||||
Your Python function can "call back" to LAMMPS through its
|
||||
library interface, if you use the SELF input to pass Python
|
||||
a pointer to LAMMPS. The mechanism for doing this in your
|
||||
Python function is as follows:
|
||||
As mentioned above, a Python function can "call back" to LAMMPS
|
||||
through its library interface, if the SELF input is used to pass
|
||||
Python a pointer to LAMMPS. The mechanism for doing this is as
|
||||
follows:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@ -416,7 +473,7 @@ which loads and runs the following function from ``examples/python/funcs.py``:
|
||||
|
||||
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 %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("run 10") # ditto
|
||||
@ -449,9 +506,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
|
||||
return statement. This cutoff value in the "cut" variable is then
|
||||
substituted (by LAMMPS) in the pair_style command that is executed
|
||||
next. Alternatively, the "LAMMPS command option" line could be used
|
||||
in place of the 2 preceding lines, to have Python insert the value
|
||||
into the LAMMPS command string.
|
||||
next. Alternatively, the "alternate form of LAMMPS command" line
|
||||
could be used in place of the 2 preceding lines, to have Python insert
|
||||
the value into the LAMMPS command string.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -463,20 +520,109 @@ into the LAMMPS command string.
|
||||
file() functions, so long as the command would work if it were
|
||||
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 or atom-style varaible. This means the Python function
|
||||
will be invoked whenever the variable is invoked. In the case of an
|
||||
atom-style varaible, the Python function can be invoked once per atom.
|
||||
|
||||
Here are two simple examples using equal- 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 atom-style
|
||||
varaibles 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
|
||||
|
||||
Now 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
|
||||
varaible formula or by *input* keyword to the *python command. 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_flags &
|
||||
format fffffsf here """
|
||||
def mixedargs(a,b,x,y,z,flags):
|
||||
...
|
||||
return result
|
||||
"""
|
||||
variable flags 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 arguements (7.5,v_myValue,v_flags) 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 teach 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 +709,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
|
||||
LAMMPS. LAMMPS must also be built as a shared library and your Python
|
||||
function must be able to load the :doc:`"lammps" Python module
|
||||
<Python_module>` that wraps the LAMMPS library interface. These are the
|
||||
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.
|
||||
Note that it is important that the stand-alone LAMMPS executable and the
|
||||
LAMMPS shared library be 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.
|
||||
<Python_module>` that wraps the LAMMPS library interface.
|
||||
|
||||
These are the 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. Note that it is important that the
|
||||
stand-alone LAMMPS executable and the LAMMPS shared library be
|
||||
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
|
||||
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
|
||||
shared library. If the Python interpreter is linked to Python
|
||||
statically (which seems to happen with Conda) then loading the shared
|
||||
LAMMPS library will create a second python "main" module that hides the
|
||||
one from the Python interpreter and all previous defined function and
|
||||
global variables will become invisible.
|
||||
LAMMPS library will create a second python "main" module that hides
|
||||
the one from the Python interpreter and all previous defined function
|
||||
and global variables will become invisible.
|
||||
|
||||
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
|
||||
"""""""
|
||||
|
||||
Reference in New Issue
Block a user