doc pages for new Python function wrappers

This commit is contained in:
Steve Plimpton
2025-05-01 12:41:48 -06:00
parent 19d25a3654
commit 76d0ead245
5 changed files with 333 additions and 22 deletions

View File

@ -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

View File

@ -73,7 +73,7 @@ Syntax
is_typelabel(kind,label), is_timeout() is_typelabel(kind,label), is_timeout()
feature functions = is_available(category,feature), is_active(category,feature), feature functions = is_available(category,feature), is_active(category,feature),
is_defined(category,id) is_defined(category,id)
python function = py_varname(x,y,z,...) 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]
@ -545,9 +545,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, the python function, functions, special functions, feature functions, python function
atom values, atom vectors, custom atom properties, compute references, wrappers, atom values, atom vectors, custom atom properties, compute
fix references, and references to other 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 |
@ -567,7 +567,8 @@ fix references, and references to other variables.
| 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), 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) | | Feature functions | is_available(category,feature), is_active(category,feature), is_defined(category,id) |
+------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Python function | py_varname(x,y,z,...) | +------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Python function wrappers | 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] |
+------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@ -1179,20 +1180,76 @@ variable name.
---------- ----------
Python Function Python Function wrappers
----------------- ------------------------
NOTE: this needs work A Python function wrapper enables the formula for an equal-style or
explain why use this versus just reference a python variable atom-style variable to invoke functions coded in Python. In the case
(b/c can pass args) of an equal-style variable, the Python-coded function will be invoked
(b/c can use it in an atom-style varible) 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.
Math operators are written in the usual way, where the "x" and "y" in The syntax for defining a Python function wrapper is
the examples can themselves be arbitrarily complex formulas, as in the
examples above. In this syntax, "x" and "y" can be scalar values or .. code-block:: LAMMPS
per-atom vectors. For example, "ke/natoms" is the division of two
scalars, where "vy+vz" is the element-by-element sum of two per-atom py_varname(arg1,arg2,...argN)
vectors of y and z velocities.
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_pyarg1 format fi here """
def truncate(x):
return int(x)
"""
variable pyarg1 internal 0.0
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 *variable pyarg1* command defines an internal-style variable. It
MUST have the name pyarg1. If the Python function has *N* arguments,
*N* internal-style variables MUST be defined with names *pyarg1*,
*pyarg2*, ... *pyargN*. Note that multiple Python function wrappers
can use the same internal-style variables.
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 x-coord of the
Ith atom becomes the value of the *pyarg1* internal-style variable.
The call to the *truncate()* function uses the value of the *pyarg1*
variable as its first (and only) argument.
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.
---------- ----------

View File

@ -0,0 +1,46 @@
# 3d Lennard-Jones melt with equal- and atom-style variables which
# use a Python function wrapper in their formulas
variable x index 5
variable y index 5
variable z index 5
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
variable foo python truncate
python truncate return v_foo input 1 v_pyarg1 format fi here """
def truncate(x):
return int(x)
"""
variable pyarg1 internal 0.0
variable scalar equal py_foo(4.5)
print "TRUNCATE ${scalar}"
variable xtrunc atom py_foo(x)
variable ytrunc atom py_foo(y)
variable ztrunc atom py_foo(z)
# examine dump file to see truncated xyz coords of each atom
#dump 1 all custom 100 tmp.dump id x y z
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
run 100

View File

@ -0,0 +1,99 @@
LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-125-g7ca493917a-modified)
# 3d Lennard-Jones melt with equal- and atom-style variables which
# use a Python function wrapper in their formulas
variable x index 5
variable y index 5
variable z index 5
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 5 0 $y 0 $z
region box block 0 5 0 5 0 $z
region box block 0 5 0 5 0 5
create_box 1 box
Created orthogonal box = (0 0 0) to (8.397981 8.397981 8.397981)
1 by 1 by 1 MPI processor grid
create_atoms 1 box
Created 500 atoms
using lattice units in orthogonal box = (0 0 0) to (8.397981 8.397981 8.397981)
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
variable foo python truncate
python truncate return v_foo input 1 v_pyarg1 format fi here """
def truncate(x):
return int(x)
"""
variable pyarg1 internal 0.0
variable scalar equal py_foo(4.5)
print "TRUNCATE ${scalar}"
TRUNCATE 4
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
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
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 = 6 6 6
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.644 | 2.644 | 2.644 Mbytes
Step Temp E_pair E_mol TotEng Press
0 1.44 -6.7733681 0 -4.6176881 -5.0221006
100 0.75627408 -5.7580082 0 -4.6258659 0.21870071
Loop time of 0.0160255 on 1 procs for 100 steps with 500 atoms
Performance: 2695709.610 tau/day, 6240.069 timesteps/s, 3.120 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.011326 | 0.011326 | 0.011326 | 0.0 | 70.67
Neigh | 0.002924 | 0.002924 | 0.002924 | 0.0 | 18.25
Comm | 0.00046255 | 0.00046255 | 0.00046255 | 0.0 | 2.89
Output | 0.0010398 | 0.0010398 | 0.0010398 | 0.0 | 6.49
Modify | 0.00020589 | 0.00020589 | 0.00020589 | 0.0 | 1.28
Other | | 6.725e-05 | | | 0.42
Nlocal: 500 ave 500 max 500 min
Histogram: 1 0 0 0 0 0 0 0 0 0
Nghost: 1941 ave 1941 max 1941 min
Histogram: 1 0 0 0 0 0 0 0 0 0
Neighs: 18766 ave 18766 max 18766 min
Histogram: 1 0 0 0 0 0 0 0 0 0
Total # of neighbors = 18766
Ave neighs/atom = 37.532
Neighbor list builds = 5
Dangerous builds not checked
Total wall time: 0:00:00

View File

@ -0,0 +1,99 @@
LAMMPS (2 Apr 2025 - Development - patch_2Apr2025-125-g7ca493917a-modified)
# 3d Lennard-Jones melt with equal- and atom-style variables which
# use a Python function wrapper in their formulas
variable x index 5
variable y index 5
variable z index 5
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 5 0 $y 0 $z
region box block 0 5 0 5 0 $z
region box block 0 5 0 5 0 5
create_box 1 box
Created orthogonal box = (0 0 0) to (8.397981 8.397981 8.397981)
1 by 2 by 2 MPI processor grid
create_atoms 1 box
Created 500 atoms
using lattice units in orthogonal box = (0 0 0) to (8.397981 8.397981 8.397981)
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
variable foo python truncate
python truncate return v_foo input 1 v_pyarg1 format fi here """
def truncate(x):
return int(x)
"""
variable pyarg1 internal 0.0
variable scalar equal py_foo(4.5)
print "TRUNCATE ${scalar}"
TRUNCATE 4
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
dump 1 all custom 100 tmp.dump id x y z v_xtrunc v_ytrunc v_ztrunc
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 = 6 6 6
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.609 | 2.609 | 2.609 Mbytes
Step Temp E_pair E_mol TotEng Press
0 1.44 -6.7733681 0 -4.6176881 -5.0221006
100 0.75627408 -5.7580082 0 -4.6258659 0.21870071
Loop time of 0.00641075 on 4 procs for 100 steps with 500 atoms
Performance: 6738684.275 tau/day, 15598.806 timesteps/s, 7.799 Matom-step/s
100.0% 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.0028061 | 0.0028831 | 0.0029657 | 0.1 | 44.97
Neigh | 0.00086635 | 0.00088279 | 0.00089739 | 0.0 | 13.77
Comm | 0.0020095 | 0.0020768 | 0.0021521 | 0.1 | 32.40
Output | 0.00041634 | 0.00042457 | 0.00043221 | 0.0 | 6.62
Modify | 6.2967e-05 | 6.4188e-05 | 6.5205e-05 | 0.0 | 1.00
Other | | 7.934e-05 | | | 1.24
Nlocal: 125 ave 126 max 123 min
Histogram: 1 0 0 0 0 0 1 0 0 2
Nghost: 1085.75 ave 1090 max 1082 min
Histogram: 1 0 1 0 0 0 1 0 0 1
Neighs: 4691.5 ave 4969 max 4368 min
Histogram: 1 0 0 0 1 0 0 1 0 1
Total # of neighbors = 18766
Ave neighs/atom = 37.532
Neighbor list builds = 5
Dangerous builds not checked
Total wall time: 0:00:00