Files
lammps/doc/src/python.rst

777 lines
34 KiB
ReStructuredText

.. index:: python
python command
==============
Syntax
""""""
.. code-block:: LAMMPS
python mode keyword args ...
* mode = *source* or *name* of Python function
if mode is *source*:
.. parsed-literal::
keyword = *here* or name of a *Python file*
*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 *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 = invoke the previously-defined Python function
logreturn = log return value of the invoked python function, if defined (optional)
*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 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
*length* arg = Nlen
Nlen = max length of string returned from Python function
*file* arg = filename
filename = file of Python code, which defines the Python function
*here* arg = inline
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
Examples
""""""""
.. code-block:: LAMMPS
python pForce input 2 v_x 20.0 return v_f format fff file force.py
python pForce invoke logreturn
python factorial input 1 myN return v_fac format ii here """
def factorial(n):
if n == 1: return n
return n * factorial(n-1)
"""
python loop input 1 SELF return v_value format pf here """
def loop(lmpptr,N,cut0):
from lammps import lammps
lmp = lammps(ptr=lmpptr)
# loop N times, increasing cutoff each time
for i in range(N):
cut = cut0 + i*0.1
lmp.set_variable("cut",cut) # set a variable in LAMMPS
lmp.command("pair_style lj/cut ${cut}") # LAMMPS commands
lmp.command("pair_coeff * * 1.0 1.0")
lmp.command("run 100")
"""
python source funcdef.py
python source here "from lammps import lammps"
Description
"""""""""""
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.
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, vector-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-, vector-, 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 that python-style, equal-style, vectir-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.
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
illustrates use 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 *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
may already be defined (see *exists* keyword) or must be defined using
the *file* or *here* keywords as explained below.
If the *invoke* keyword is used, only the optional *logreturn* keyword
can be used. A previous *python* command must have registered the
Python function referenced by this command. The command invokes the
Python function with the previously defined arguments. A return value
of the Python function will be ignored unless the Python function is
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
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 *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 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
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.
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. 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
variable foo python myMultiply
python myMultiply return v_foo format f file funcs.py
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.
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.
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. 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.
----------
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
using triple quotes as delimiters, as in the examples above. This
allows Python code to be listed verbatim in your input script, with
proper indentation, blank lines, and comments, as desired. See the
:doc:`Commands parse <Commands_parse>` doc page, for an explanation of
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. 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 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.
----------
This section describes how Python code can be written to work with
LAMMPS.
Whether you load Python code from a file or directly from your input
script, via the *file* and *here* keywords, the code can be identical.
It must be indented properly as Python requires. It can contain
comments or blank lines. If the code is in your input script, it cannot
however contain triple-quoted Python strings, since that will conflict
with the triple-quote parsing that the LAMMPS input script performs.
All the Python code you specify via one or more python commands is
loaded into the Python "main" module, i.e. ``__name__ == '__main__'``.
The code can define global variables, define global functions, define
classes or execute statements that are outside of function definitions.
It can contain multiple functions, only one of which matches the *func*
setting in the python command. This means you can use the *file*
keyword once to load several functions, and the *exists* keyword
thereafter in subsequent python commands to register the other functions
that were previously loaded with LAMMPS.
A Python function you define (or more generally, the code you load)
can import other Python modules or classes, it can make calls to other
system functions or functions you define, and it can access or modify
global variables (in the "main" module) which will persist between
successive function calls. The latter can be useful, for example, to
prevent a function from being invoke multiple times per timestep by
different commands in a LAMMPS input script that access the returned
python-style variable associated with the function. For example,
consider this function loaded with two global variables defined
outside the function:
.. code-block:: python
nsteplast = -1
nvaluelast = 0
def expensive(nstep):
global nsteplast,nvaluelast
if nstep == nsteplast: return nvaluelast
nsteplast = nstep
# perform complicated calculation
nvalue = ...
nvaluelast = nvalue
return nvalue
The variable 'nsteplast' stores the previous timestep the function was
invoked (passed as an argument to the function). The variable
'nvaluelast' stores the return value computed on the last function
invocation. If the function is invoked again on the same timestep, the
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.
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
copy of the Python function(s) you define. There is no connection
between the Python interpreters running on different processors.
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.
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
python python_hello input 1 SELF format p here """
def python_hello(handle):
from lammps import lammps
lmp = lammps(ptr=handle)
me = lmp.extract_setting('world_rank')
if me == 0:
print('Hello, LAMMPS!')
"""
python python_hello invoke
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
global communication (e.g. via MPI_Allreduce), such as computing the
global temperature of the system, then you must ensure all your Python
functions (running independently on different processors) call back to
LAMMPS. Otherwise the code may hang.
----------
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
def foo(handle,...):
from lammps import lammps
lmp = lammps(ptr=handle)
lmp.command('print "Hello from inside Python"')
...
The function definition must include a variable ('handle' in this case)
which corresponds to SELF in the *python* command. The first line of
the function imports the :doc:`"lammps" Python module <Python_module>`.
The second line creates a Python object ``lmp`` which wraps the instance
of LAMMPS that called the function. The 'ptr=handle' argument is what
makes that happen. The third line invokes the command() function in the
LAMMPS library interface. It takes a single string argument which is a
LAMMPS input script command for LAMMPS to execute, the same as if it
appeared in your input script. In this case, LAMMPS should output
.. parsed-literal::
Hello from inside Python
to the screen and log file. Note that since the LAMMPS print command
itself takes a string in quotes as its argument, the Python string
must be delimited with a different style of quotes.
The :doc:`Python_head` page describes the syntax
for how Python wraps the various functions included in the LAMMPS
library interface.
A more interesting example is in the ``examples/python/in.python`` script
which loads and runs the following function from ``examples/python/funcs.py``:
.. code-block:: python
def loop(N,cut0,thresh,lmpptr):
print("LOOP ARGS", N, cut0, thresh, lmpptr)
from lammps import lammps
lmp = lammps(ptr=lmpptr)
natoms = lmp.get_natoms()
for i in range(N):
cut = cut0 + i*0.1
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) # alternate form of LAMMPS command
lmp.command("pair_coeff * * 1.0 1.0") # ditto
lmp.command("run 10") # ditto
pe = lmp.extract_compute("thermo_pe",0,0) # extract total PE from LAMMPS
print("PE", pe/natoms, thresh)
if pe/natoms < thresh: return
with these input script commands:
.. code-block:: LAMMPS
python loop input 4 10 1.0 -4.0 SELF format iffp file funcs.py
python loop invoke
This has the effect of looping over a series of 10 short runs (10
timesteps each) where the pair style cutoff is increased from a value
of 1.0 in distance units, in increments of 0.1. The looping stops
when the per-atom potential energy falls below a threshold of -4.0 in
energy units. More generally, Python can be used to implement a loop
with complex logic, much more so than can be created using the LAMMPS
:doc:`jump <jump>` and :doc:`if <if>` commands.
Several LAMMPS library functions are called from the loop function.
Get_natoms() returns the number of atoms in the simulation, so that it
can be used to normalize the potential energy that is returned by
extract_compute() for the "thermo_pe" compute that is defined by
default for LAMMPS thermodynamic output. Set_variable() sets the
value of a string variable defined in LAMMPS. This library function
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 "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::
When using the callback mechanism just described, recognize that
there are some operations you should not attempt because LAMMPS cannot
execute them correctly. If the Python function is invoked between
runs in the LAMMPS input script, then it should be OK to invoke any
LAMMPS input script command via the library interface command() or
file() functions, so long as the command would work if it were
executed in the LAMMPS input script directly at the same point.
----------
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 varaible. 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
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_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 arguements (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.
----------
If you run Python code directly on your workstation, either
interactively or by using Python to launch a Python script stored in a
file, and your code has an error, you will typically see informative
error messages. That is not the case when you run Python code from
LAMMPS using an embedded Python interpreter. The code will typically
fail silently. LAMMPS will catch some errors but cannot tell you
where in the Python code the problem occurred. For example, if the
Python code cannot be loaded and run because it has syntax or other
logic errors, you may get an error from Python pointing to the
offending line, or you may get one of these generic errors from
LAMMPS:
.. parsed-literal::
Could not process Python file
Could not process Python string
When the Python function is invoked, if it does not return properly,
you will typically get this generic error from LAMMPS:
.. parsed-literal::
Python function evaluation failed
Here are three suggestions for debugging your Python code while
running it under LAMMPS.
First, don't run it under LAMMPS, at least to start with! Debug it
using plain Python. Load and invoke your function, pass it arguments,
check return values, etc.
Second, add Python print statements to the function to check how far
it gets and intermediate values it calculates. See the discussion
above about printing from Python when running in parallel.
Third, use Python exception handling. For example, say this statement
in your Python function is failing, because you have not initialized the
variable foo:
.. code-block:: python
foo += 1
If you put one (or more) statements inside a "try" statement,
like this:
.. code-block:: python
import exceptions
print("Inside simple function")
try:
foo += 1 # one or more statements here
except Exception as e:
print("FOO error:", e)
then you will get this message printed to the screen:
.. parsed-literal::
FOO error: local variable 'foo' referenced before assignment
If there is no error in the try statements, then nothing is printed.
Either way the function continues on (unless you put a return or
sys.exit() in the except clause).
----------
Restrictions
""""""""""""
This command is part of the PYTHON package. It is only enabled if
LAMMPS was built with that package. See the :doc:`Build package
<Build_package>` page for more info.
Building LAMMPS with the PYTHON package will link LAMMPS with the Python
library on your system. Settings to enable this are in the
lib/python/Makefile.lammps file. See the lib/python/README file for
information on those settings.
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.
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.
Related commands
""""""""""""""""
:doc:`shell <shell>`, :doc:`variable <variable>`, :doc:`fix
python/invoke <fix_python_invoke>`
Default
"""""""
none