diff --git a/doc/Manual.html b/doc/Manual.html
index 5b7b88a9b3..d99c450e8f 100644
--- a/doc/Manual.html
+++ b/doc/Manual.html
@@ -245,17 +245,21 @@ it gives quick access to documentation for all LAMMPS commands.
Here is how each line in the input script is parsed by LAMMPS:
-(1) If the last printable character on the line is a "&" character -(with no surrounding quotes), the command is assumed to continue on -the next line. The next line is concatenated to the previous line by -removing the "&" character and newline. This allows long commands to -be continued across two or more lines. +
(1) If the last printable character on the line is a "&" character, +the command is assumed to continue on the next line. The next line is +concatenated to the previous line by removing the "&" character and +line break. This allows long commands to be continued across two or +more lines. See the discussion of triple quotes in (6) for how to +continue a command across multiple line without using "&" characters.
(2) All characters from the first "#" character onward are treated as comment and discarded. See an exception in (6). Note that a @@ -136,9 +137,9 @@ variable X delete contain nested $ characters for other variables to substitute for. Thus you cannot do this:
-variable a equal 2 -variable b2 equal 4 -region 1 block ${b$a} 2 INF INF EDGE EDGE +variable a equal 2 +variable b2 equal 4 +print "B2 = ${b$a}"Nor can you specify this $($x-1.0) for an immediate variable, but you could use $(v_x-1.0), since the latter is valid syntax for an @@ -156,27 +157,38 @@ underscores, or punctuation characters. line are arguments.
(6) If you want text with spaces to be treated as a single argument, -it can be enclosed in either double or single quotes. A long single -argument enclosed in quotes can even span multiple lines if the "&" -character is used, as described above. E.g. +it can be enclosed in either single or double or triple quotes. A +long single argument enclosed in single or double quotes can span +multiple lines if the "&" character is used, as described above. When +the lines are concatenated together (and the "&" characters and line +breaks removed), the text will become a single line. If you want +multiple lines of an argument to retain their line breaks, the text +can be enclosed in triple quotes, in which case "&" characters are not +needed. For example:
print "Volume = $v" print 'Volume = $v' +if "$steps > 1000" then quit variable a string "red green blue & purple orange cyan" -if "$steps > 1000" then quit +print """ +System volume = $v +System temperature = $t +"""-The quotes are removed when the single argument is stored internally. +
In each case, the single, double, or triple quotes are removed when +the single argument they enclose is stored internally.
-See the dump modify format or print or -if commands for examples. A "#" or "$" character that is -between quotes will not be treated as a comment indicator in (2) or -substituted for as a variable in (3). +
See the dump modify format, print, +if, and python commands for examples. +
+A "#" or "$" character that is between quotes will not be treated as a +comment indicator in (2) or substituted for as a variable in (3).
IMPORTANT NOTE: If the argument is itself a command that requires a quoted argument (e.g. using a print command as part of an -if or run every command), then the double and -single quotes can be nested in the usual manner. See the doc pages +if or run every command), then single, double, or +triple quotes can be nested in the usual manner. See the doc pages for those commands for examples. Only one of level of nesting is allowed, but that should be sufficient for most use cases.
@@ -407,12 +419,12 @@ g = GPU, i = USER-INTEL, k = KOKKOS, o = USER-OMP, t = OPT.npt (co) npt/asphere (o) npt/sphere (o) nve (cko) nve/asphere nve/asphere/noforce nve/body nve/limit nve/line nve/noforce nve/sphere (o) nve/tri nvt (co) nvt/asphere (o) nvt/sllod (o) nvt/sphere (o) - oneway orient/fcc planeforce poems pour press/berendsen property/atom - qeq/comb (o) qeq/dynamic qeq/point qeq/shielded qeq/slater rattle reax/bonds recenter - restrain rigid (o) rigid/nph (o) rigid/npt (o) rigid/nve (o) rigid/nvt (o) rigid/small (o) rigid/small/nph - rigid/small/npt rigid/small/nve rigid/small/nvt setforce (c) shake (c) spring spring/rg spring/self - srd store/force store/state temp/berendsen (c) temp/csvr temp/rescale (c) tfmc thermal/conductivity - tmd ttm tune/kspace vector viscosity viscous (c) wall/colloid wall/gran wall/harmonic wall/lj1043 wall/lj126 wall/lj93 wall/piston wall/reflect wall/region wall/srd + + qeq/comb (o) qeq/dynamic qeq/point qeq/shielded qeq/slater reax/bonds recenter restrain + rigid (o) rigid/nph (o) rigid/npt (o) rigid/nve (o) rigid/nvt (o) rigid/small (o) rigid/small/nph rigid/small/npt + rigid/small/nve rigid/small/nvt setforce (c) shake (c) spring spring/rg spring/self srd + store/force store/state temp/berendsen (c) temp/csvr temp/rescale (c) tfmc thermal/conductivity tmd + ttm tune/kspace vector viscosity viscous (c) wall/colloid wall/gran wall/harmonic wall/lj1043 wall/lj126 wall/lj93 wall/piston wall/reflect wall/region wall/srd These are additional fix styles in USER packages, which can be used if @@ -449,9 +461,9 @@ KOKKOS, o = USER-OMP, t = OPT.
msd/chunk msd/nongauss pair pair/local pe (c) pe/atom plasticity/atom pressure (c) property/atom property/local property/chunk rdf - reduce reduce/region slice sna/atom snad/atom snav/atom - stress/atom temp (c) temp/asphere temp/com temp/chunk temp/cs - temp/deform temp/partial (c) temp/profile temp/ramp temp/region temp/sphere ti torque/chunk vacf vcm/chunk voronoi/atom + + stress/atom temp (c) temp/asphere temp/com temp/chunk temp/deform + temp/partial (c) temp/profile temp/ramp temp/region temp/sphere ti torque/chunk vacf vcm/chunk voronoi/atom These are additional compute styles in USER packages, which can be @@ -478,31 +490,30 @@ KOKKOS, o = USER-OMP, t = OPT.
These are additional pair styles in USER packages, which can be used diff --git a/doc/Section_commands.txt b/doc/Section_commands.txt index c6d4b3d655..95fa426074 100644 --- a/doc/Section_commands.txt +++ b/doc/Section_commands.txt @@ -82,11 +82,12 @@ file names or user-chosen ID strings. Here is how each line in the input script is parsed by LAMMPS: -(1) If the last printable character on the line is a "&" character -(with no surrounding quotes), the command is assumed to continue on -the next line. The next line is concatenated to the previous line by -removing the "&" character and newline. This allows long commands to -be continued across two or more lines. +(1) If the last printable character on the line is a "&" character, +the command is assumed to continue on the next line. The next line is +concatenated to the previous line by removing the "&" character and +line break. This allows long commands to be continued across two or +more lines. See the discussion of triple quotes in (6) for how to +continue a command across multiple line without using "&" characters. (2) All characters from the first "#" character onward are treated as comment and discarded. See an exception in (6). Note that a @@ -132,9 +133,9 @@ Note that neither the curly-bracket or immediate form of variables can contain nested $ characters for other variables to substitute for. Thus you cannot do this: -variable a equal 2 -variable b2 equal 4 -region 1 block $\{b$a\} 2 INF INF EDGE EDGE :pre +variable a equal 2 +variable b2 equal 4 +print "B2 = $\{b$a\}" :pre Nor can you specify this $($x-1.0) for an immediate variable, but you could use $(v_x-1.0), since the latter is valid syntax for an @@ -152,27 +153,38 @@ underscores, or punctuation characters. line are arguments. (6) If you want text with spaces to be treated as a single argument, -it can be enclosed in either double or single quotes. A long single -argument enclosed in quotes can even span multiple lines if the "&" -character is used, as described above. E.g. +it can be enclosed in either single or double or triple quotes. A +long single argument enclosed in single or double quotes can span +multiple lines if the "&" character is used, as described above. When +the lines are concatenated together (and the "&" characters and line +breaks removed), the text will become a single line. If you want +multiple lines of an argument to retain their line breaks, the text +can be enclosed in triple quotes, in which case "&" characters are not +needed. For example: print "Volume = $v" print 'Volume = $v' +if "${steps} > 1000" then quit variable a string "red green blue & purple orange cyan" -if "${steps} > 1000" then quit :pre +print """ +System volume = $v +System temperature = $t +""" :pre -The quotes are removed when the single argument is stored internally. +In each case, the single, double, or triple quotes are removed when +the single argument they enclose is stored internally. -See the "dump modify format"_dump_modify.html or "print"_print.html or -"if"_if.html commands for examples. A "#" or "$" character that is -between quotes will not be treated as a comment indicator in (2) or -substituted for as a variable in (3). +See the "dump modify format"_dump_modify.html, "print"_print.html, +"if"_if.html, and "python"_python.html commands for examples. + +A "#" or "$" character that is between quotes will not be treated as a +comment indicator in (2) or substituted for as a variable in (3). IMPORTANT NOTE: If the argument is itself a command that requires a quoted argument (e.g. using a "print"_print.html command as part of an -"if"_if.html or "run every"_run.html command), then the double and -single quotes can be nested in the usual manner. See the doc pages +"if"_if.html or "run every"_run.html command), then single, double, or +triple quotes can be nested in the usual manner. See the doc pages for those commands for examples. Only one of level of nesting is allowed, but that should be sufficient for most use cases. @@ -535,7 +547,6 @@ g = GPU, i = USER-INTEL, k = KOKKOS, o = USER-OMP, t = OPT. "qeq/point"_fix_qeq.html, "qeq/shielded"_fix_qeq.html, "qeq/slater"_fix_qeq.html, -"rattle"_fix_shake.html, "reax/bonds"_fix_reax_bonds.html, "recenter"_fix_recenter.html, "restrain"_fix_restrain.html, @@ -681,7 +692,6 @@ KOKKOS, o = USER-OMP, t = OPT. "temp/asphere"_compute_temp_asphere.html, "temp/com"_compute_temp_com.html, "temp/chunk"_compute_temp_chunk.html, -"temp/cs"_compute_temp_cs.html, "temp/deform"_compute_temp_deform.html, "temp/partial (c)"_compute_temp_partial.html, "temp/profile"_compute_temp_profile.html, @@ -733,7 +743,6 @@ KOKKOS, o = USER-OMP, t = OPT. "bop"_pair_bop.html, "born (go)"_pair_born.html, "born/coul/long (cgo)"_pair_born.html, -"born/coul/long/cs"_pair_cs.html, "born/coul/msm (o)"_pair_born.html, "born/coul/wolf (go)"_pair_born.html, "brownian (o)"_pair_brownian.html, @@ -741,7 +750,6 @@ KOKKOS, o = USER-OMP, t = OPT. "buck (cgko)"_pair_buck.html, "buck/coul/cut (cgo)"_pair_buck.html, "buck/coul/long (cgo)"_pair_buck.html, -"buck/coul/long/cs"_pair_cs.html, "buck/coul/msm (o)"_pair_buck.html, "buck/long/coul/long (o)"_pair_buck_long.html, "colloid (go)"_pair_colloid.html, @@ -817,7 +825,7 @@ KOKKOS, o = USER-OMP, t = OPT. "resquared (go)"_pair_resquared.html, "snap"_pair_snap.html, "soft (go)"_pair_soft.html, -"sw (cgio)"_pair_sw.html, +"sw (cgo)"_pair_sw.html, "table (gko)"_pair_table.html, "tersoff (co)"_pair_tersoff.html, "tersoff/mod (o)"_pair_tersoff_mod.html, diff --git a/doc/Section_packages.html b/doc/Section_packages.html index 4a8cf7da40..39d5e69af4 100644 --- a/doc/Section_packages.html +++ b/doc/Section_packages.html @@ -63,6 +63,7 @@ packages, more details are provided.
OPT optimized pair styles Fischer & Richie & Natoli (2) Section accelerate - - PERI Peridynamics models Mike Parks (Sandia) pair_style peri peri - + POEMS coupled rigid body motion Rudra Mukherjee (JPL) fix poems rigid lib/poems PYTHON embed Python code in an input script - python python lib/python REAX ReaxFF potential Aidan Thompson (Sandia) pair_style reax reax lib/reax REPLICA multi-replica methods - Section_howto 6.5 tad - diff --git a/doc/Section_packages.txt b/doc/Section_packages.txt index a38931ac7d..38671c1a47 100644 --- a/doc/Section_packages.txt +++ b/doc/Section_packages.txt @@ -58,6 +58,7 @@ MOLECULE, molecular system force fields, -, "Section_howto 6.3"_Section_howto.ht OPT, optimized pair styles, Fischer & Richie & Natoli (2), "Section accelerate"_accelerate_opt.html, -, - PERI, Peridynamics models, Mike Parks (Sandia), "pair_style peri"_pair_peri.html, peri, - POEMS, coupled rigid body motion, Rudra Mukherjee (JPL), "fix poems"_fix_poems.html, rigid, lib/poems +PYTHON, embed Python code in an input script, -, "python"_python.html, python, lib/python REAX, ReaxFF potential, Aidan Thompson (Sandia), "pair_style reax"_pair_reax.html, reax, lib/reax REPLICA, multi-replica methods, -, "Section_howto 6.5"_Section_howto.html#howto_5, tad, - RIGID, rigid bodies, -, "fix rigid"_fix_rigid.html, rigid, - diff --git a/doc/Section_python.html b/doc/Section_python.html index 4b0d737b4f..705538c9a4 100644 --- a/doc/Section_python.html +++ b/doc/Section_python.html @@ -11,61 +11,98 @@ RIGID rigid bodies - fix rigid rigid - 11. Python interface to LAMMPS
-This section describes how to build and use LAMMPS via a Python -interface. +
LAMMPS can work together with Python in two ways. First, Python can +wrap LAMMPS through the LAMMPS library +interface, so that a Python script can +create one or more instances of LAMMPS and launch one or more +simulations. In Python lingo, this is "extending" Python with LAMMPS.
-
Second, LAMMPS can use the Python interpreter, so that a LAMMPS input +script can invoke Python code, and pass information back-and-forth +between the input script and Python functions you write. The Python +code can also callback to LAMMPS to query or change its attributes. +In Python lingo, this is "embedding" Python in LAMMPS. +
+This section describes how to do both. +
+The LAMMPS distribution includes the file python/lammps.py which wraps -the library interface to LAMMPS. This file makes it is possible to -run LAMMPS, invoke LAMMPS commands or give it an input script, extract -LAMMPS results, an modify internal LAMMPS variables, either from a -Python script or interactively from a Python prompt. You can do the -former in serial or parallel. Running Python interactively in -parallel does not generally work, unless you have a package installed -that extends your Python to enable multiple instances of Python to -read what you type. +
If you are not familiar with it, Python is a +powerful scripting and programming language which can essentially do +anything that faster, lower-level languages like C or C++ can do, but +typically with much fewer lines of code. When used in embedded mode, +Python can perform operations that the simplistic LAMMPS input script +syntax cannot. Python can be also be used as a "glue" language to +drive a program through its library interface, or to hook multiple +pieces of software together, such as a simulation package plus a +visualization package, or to run a coupled multiscale or multiphysics +model.
-Python is a powerful scripting and programming -language which can be used to wrap software like LAMMPS and other -packages. It can be used to glue multiple pieces of software -together, e.g. to run a coupled or multiscale model. See Section -section of the manual and the couple -directory of the distribution for more ideas about coupling LAMMPS to -other codes. See Section_start 4 about -how to build LAMMPS as a library, and Section_howto -19 for a description of the library -interface provided in src/library.cpp and src/library.h and how to -extend it for your needs. As described below, that interface is what -is exposed to Python. It is designed to be easy to add functions to. -This can easily extend the Python inteface as well. See details -below. +
See Section_howto 10 of the manual and +the couple directory of the distribution for more ideas about coupling +LAMMPS to other codes. See Section_howto +19 for a description of the LAMMPS +library interface provided in src/library.cpp and src/library.h, and +how to extend it for your needs. As described below, that interface +is what is exposed to Python either when calling LAMMPS from Python or +when calling Python from a LAMMPS input script and then calling back +to LAMMPS from Python code. The library interface is designed to be +easy to add functions to. Thus the Python interface to LAMMPS is also +easy to extend as well.
-By using the Python interface, LAMMPS can also be coupled with a GUI -or other visualization tools that display graphs or animations in real -time as LAMMPS runs. Examples of such scripts are inlcluded in the -python directory. +
If you create interesting Python scripts that run LAMMPS or +interesting Python functions that can be called from a LAMMPS input +script, that you think would be useful to other users, please email +them to the developers. We can +include them in the LAMMPS distribution.
-Two advantages of using Python are how concise the language is, and -that it can be run interactively, enabling rapid development and -debugging of programs. If you use it to mostly invoke costly -operations within LAMMPS, such as running a simulation for a +
The LAMMPS distribution includes a python directory with all you need +to run LAMMPS from Python. The python/lammps.py file wraps the LAMMPS +library interface, with one wrapper function per LAMMPS library +function. This file makes it is possible to do the following either +from a Python script, or interactively from a Python prompt: create +one or more instances of LAMMPS, invoke LAMMPS commands or give it an +input script, run LAMMPS incrementally, extract LAMMPS results, an +modify internal LAMMPS variables. From a Python script you can do +this in serial or parallel. Running Python interactively in parallel +does not generally work, unless you have a version of Python that +extends standard Python to enable multiple instances of Python to read +what you type. +
+To do all of this, you must first build LAMMPS as a shared library, +then insure that your Python can find the python/lammps.py file and +the shared library. These steps are explained in subsequent sections +11.3 and 11.4. Sections 11.5 and 11.6 discuss using MPI from a +parallel Python program and how to test that you are ready to use +LAMMPS from Python. Section 11.7 lists all the functions in the +current LAMMPS library interface and how to call them from Python. +
+Section 11.8 gives some examples of coupling LAMMPS to other tools via +Python. For example, LAMMPS can easily be coupled to a GUI or other +visualization tools that display graphs or animations in real time as +LAMMPS runs. Examples of such scripts are inlcluded in the python +directory. +
+Two advantages of using Python to run LAMMPS are how concise the +language is, and that it can be run interactively, enabling rapid +development and debugging of programs. If you use it to mostly invoke +costly operations within LAMMPS, such as running a simulation for a reasonable number of timesteps, then the overhead cost of invoking LAMMPS thru Python will be negligible.
-Before using LAMMPS from a Python script, you need to do two things. -You need to build LAMMPS as a dynamic shared library, so it can be -loaded by Python. And you need to tell Python how to find the library -and the Python wrapper file python/lammps.py. Both these steps are -discussed below. If you wish to run LAMMPS in parallel from Python, -you also need to extend your Python with MPI. This is also discussed -below. -
The Python wrapper for LAMMPS uses the amazing and magical (to me) "ctypes" package in Python, which auto-generates the interface code needed between Python and a set of C interface routines for a library. @@ -75,16 +112,77 @@ check which version of Python you have installed, by simply typing
LAMMPS has a python command which can be used in an +input script to define and execute a Python function that you write +the code for. The Python function can also be assigned to a LAMMPS +python-style variable via the variable command. Each +time the variable is evaluated, either in the LAMMPS input script +itself, or by another LAMMPS command that uses the variable, this will +trigger the Python function to be invoked. +
+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 +are mapped to LAMMPS variables (also defined in the input script) and +it can return a value to a LAMMPS variable. This is thus a mechanism +for your input script to pass information to a piece of Python code, +ask Python to execute the code, and return information to your input +script. +
+Note that a Python function can be arbitrarily complex. It can import +other Python modules, instantiate Python classes, call other Python +functions, etc. The Python code that you provide can contain more +code than the single function. It can contain other functions or +Python classes, as well as global variables or other mechanisms for +storing state between calls from LAMMPS to the function. +
+The Python function you provide can consist of "pure" Python code that +only performs operations provided by standard Python. However, the +Python function can also "call back" to LAMMPS through its +Python-wrapped library interface, in the manner described in the +previous section 11.1. This means it can issue LAMMPS input script +commands or query and set internal LAMMPS state. As an example, this +can be useful in an input script to create a more complex loop with +branching logic, than can be created using the simple looping and +brancing logic enabled by the next and if +commands. +
+See the python doc page and the variable +doc page for its python-style variables for more info, including +examples of Python code you can write for both pure Python operations +and callbacks to LAMMPS. +
+To run pure Python code from LAMMPS, you only need to build LAMMPS +with the PYTHON package installed: +
+make yes-python +make machine +
+Note that this will link LAMMPS with the Python library on your +system, which typically requires several auxiliary system libraries to +also be linked. The list of these libraries and the paths to find +them are specified in the lib/python/Makefile.lammps file. You need +to insure that file contains the correct information for your version +of Python and your machine to successfully build LAMMPS. See the +lib/python/README file for more info. +
+If you want to write Python code with callbacks to LAMMPS, then you +must also follow the steps overviewed in the preceeding section (11.1) +for running LAMMPS from Python. I.e. you must build LAMMPS as a +shared library and insure that Python can find the python/lammps.py +file and the shared library. +
Instructions on how to build LAMMPS as a shared library are given in Section_start 5. A shared library is one -that is dynamically loadable, which is what Python requires. On Linux -this is a library file that ends in ".so", not ".a". +that is dynamically loadable, which is what Python requires to wrap +LAMMPS. On Linux this is a library file that ends in ".so", not ".a".
-From the src directory, type +
>From the src directory, type
make foo mode=shlib@@ -102,7 +200,7 @@ system.
For Python to invoke LAMMPS, there are 2 files it needs to know about:
@@ -170,7 +268,7 @@ environment variable as described above.If you wish to run LAMMPS in parallel from Python, you need to extend your Python with an interface to MPI. This also allows you to @@ -197,11 +295,12 @@ believe) creates a new alternate executable (in place of "python" itself) as a result.
In principle any of these Python/MPI packages should work to invoke -LAMMPS in parallel and MPI calls themselves from a Python script which -is itself running in parallel. However, when I downloaded and looked -at a few of them, their documentation was incomplete and I had trouble -with their installation. It's not clear if some of the packages are -still being actively developed and supported. +LAMMPS in parallel and to make MPI calls themselves from a Python +script which is itself running in parallel. However, when I +downloaded and looked at a few of them, their documentation was +incomplete and I had trouble with their installation. It's not clear +if some of the packages are still being actively developed and +supported.
The one I recommend, since I have successfully used it with LAMMPS, is Pypar. Pypar requires the ubiquitous Numpy @@ -261,7 +360,7 @@ the right one.
To test if LAMMPS is callable from Python, launch Python interactively and type: @@ -375,22 +474,24 @@ Python on a single processor, not in parallel.
The Python interface to LAMMPS consists of a Python "lammps" module, -the source code for which is in python/lammps.py, which creates a -"lammps" object, with a set of methods that can be invoked on that -object. The sample Python code below assumes you have first imported -the "lammps" module in your Python script, as follows: +
As described above, the Python interface to LAMMPS consists of a +Python "lammps" module, the source code for which is in +python/lammps.py, which creates a "lammps" object, with a set of +methods that can be invoked on that object. The sample Python code +below assumes you have first imported the "lammps" module in your +Python script, as follows:
from lammps import lammps-
These are the methods defined by the lammps module. If you look -at the file src/library.cpp you will see that they correspond -one-to-one with calls you can make to the LAMMPS library from a C++ or -C or Fortran program. +
These are the methods defined by the lammps module. If you look at +the files src/library.cpp and src/library.h you will see that they +correspond one-to-one with calls you can make to the LAMMPS library +from a C++ or C or Fortran program.
lmp = lammps() # create a LAMMPS object using the default liblammps.so library +lmp = lammps(ptr=lmpptr) # ditto, but use lmpptr as previously created LAMMPS object lmp = lammps("g++") # create a LAMMPS object using the liblammps_g++.so library lmp = lammps("",list) # ditto, with command-line args, e.g. list = ["-echo","screen"] lmp = lammps("g++",list) @@ -449,6 +550,33 @@ processors. If someone figures out how to do this with one or more of the Python wrappers for MPI, like Pypar, please let us know and we will amend these doc pages. +The lines +
+from lammps import lammps +lmp = lammps() ++create an instance of LAMMPS, wrapped in a Python class by the lammps +Python module, and return an instance of the Python class as lmp. It +is used to make all subequent calls to the LAMMPS library. +
+Additional arguments can be used to tell Python the name of the shared +library to load or to pass arguments to the LAMMPS instance, the same +as if LAMMPS were launched from a command-line prompt. +
+If the ptr argument is set like this: +
+lmp = lammps(ptr=lmpptr) ++then lmpptr must be an argument passed to Python via the LAMMPS +python command, when it is used to define a Python +function that is invoked by the LAMMPS input script. This mode of +using Python with LAMMPS is described above in 11.2. The variable +lmpptr refers to the instance of LAMMPS that called the embedded +Python interpreter. Using it as an argument to lammps() allows the +returned Python class instance "lmp" to make calls to that instance of +LAMMPS. See the python command doc page for examples +using this syntax. +
Note that you can create multiple LAMMPS objects in your Python script, and coordinate and run multiple simulations, e.g.
@@ -578,7 +706,7 @@ Python script. Isn't ctypes amazing?
-11.6 Example Python scripts that use LAMMPS +
11.8 Example Python scripts that use LAMMPS
These are the Python scripts included as demos in the python/examples directory of the LAMMPS distribution, to illustrate the kinds of diff --git a/doc/Section_python.txt b/doc/Section_python.txt index 192d6cf21d..ae256476be 100644 --- a/doc/Section_python.txt +++ b/doc/Section_python.txt @@ -8,61 +8,97 @@ 11. Python interface to LAMMPS :h3 -This section describes how to build and use LAMMPS via a Python -interface. +LAMMPS can work together with Python in two ways. First, Python can +wrap LAMMPS through the "LAMMPS library +interface"_Section_howto.html#howto_19, so that a Python script can +create one or more instances of LAMMPS and launch one or more +simulations. In Python lingo, this is "extending" Python with LAMMPS. -11.1 "Building LAMMPS as a shared library"_#py_1 -11.2 "Installing the Python wrapper into Python"_#py_2 -11.3 "Extending Python with MPI to run in parallel"_#py_3 -11.4 "Testing the Python-LAMMPS interface"_#py_4 -11.5 "Using LAMMPS from Python"_#py_5 -11.6 "Example Python scripts that use LAMMPS"_#py_6 :ul +Second, LAMMPS can use the Python interpreter, so that a LAMMPS input +script can invoke Python code, and pass information back-and-forth +between the input script and Python functions you write. The Python +code can also callback to LAMMPS to query or change its attributes. +In Python lingo, this is "embedding" Python in LAMMPS. -The LAMMPS distribution includes the file python/lammps.py which wraps -the library interface to LAMMPS. This file makes it is possible to -run LAMMPS, invoke LAMMPS commands or give it an input script, extract -LAMMPS results, an modify internal LAMMPS variables, either from a -Python script or interactively from a Python prompt. You can do the -former in serial or parallel. Running Python interactively in -parallel does not generally work, unless you have a package installed -that extends your Python to enable multiple instances of Python to -read what you type. +This section describes how to do both. -"Python"_http://www.python.org is a powerful scripting and programming -language which can be used to wrap software like LAMMPS and other -packages. It can be used to glue multiple pieces of software -together, e.g. to run a coupled or multiscale model. See "Section -section"_Section_howto.html#howto_10 of the manual and the couple -directory of the distribution for more ideas about coupling LAMMPS to -other codes. See "Section_start 4"_Section_start.html#start_5 about -how to build LAMMPS as a library, and "Section_howto -19"_Section_howto.html#howto_19 for a description of the library -interface provided in src/library.cpp and src/library.h and how to -extend it for your needs. As described below, that interface is what -is exposed to Python. It is designed to be easy to add functions to. -This can easily extend the Python inteface as well. See details -below. +11.1 "Overview of running LAMMPS from Python"_#py_1 +11.2 "Overview of using Python from a LAMMPS script"_#py_2 +11.3 "Building LAMMPS as a shared library"_#py_3 +11.4 "Installing the Python wrapper into Python"_#py_4 +11.5 "Extending Python with MPI to run in parallel"_#py_5 +11.6 "Testing the Python-LAMMPS interface"_#py_6 +11.7 "Using LAMMPS from Python"_#py_7 +11.8 "Example Python scripts that use LAMMPS"_#py_8 :ul -By using the Python interface, LAMMPS can also be coupled with a GUI -or other visualization tools that display graphs or animations in real -time as LAMMPS runs. Examples of such scripts are inlcluded in the -python directory. +If you are not familiar with it, "Python"_http://www.python.org is a +powerful scripting and programming language which can essentially do +anything that faster, lower-level languages like C or C++ can do, but +typically with much fewer lines of code. When used in embedded mode, +Python can perform operations that the simplistic LAMMPS input script +syntax cannot. Python can be also be used as a "glue" language to +drive a program through its library interface, or to hook multiple +pieces of software together, such as a simulation package plus a +visualization package, or to run a coupled multiscale or multiphysics +model. -Two advantages of using Python are how concise the language is, and -that it can be run interactively, enabling rapid development and -debugging of programs. If you use it to mostly invoke costly -operations within LAMMPS, such as running a simulation for a +See "Section_howto 10"_Section_howto.html#howto_10 of the manual and +the couple directory of the distribution for more ideas about coupling +LAMMPS to other codes. See "Section_howto +19"_Section_howto.html#howto_19 for a description of the LAMMPS +library interface provided in src/library.cpp and src/library.h, and +how to extend it for your needs. As described below, that interface +is what is exposed to Python either when calling LAMMPS from Python or +when calling Python from a LAMMPS input script and then calling back +to LAMMPS from Python code. The library interface is designed to be +easy to add functions to. Thus the Python interface to LAMMPS is also +easy to extend as well. + +If you create interesting Python scripts that run LAMMPS or +interesting Python functions that can be called from a LAMMPS input +script, that you think would be useful to other users, please "email +them to the developers"_http://lammps.sandia.gov/authors.html. We can +include them in the LAMMPS distribution. + +:line +:line + +11.1 Overview of running LAMMPS from Python :link(py_1),h4 + +The LAMMPS distribution includes a python directory with all you need +to run LAMMPS from Python. The python/lammps.py file wraps the LAMMPS +library interface, with one wrapper function per LAMMPS library +function. This file makes it is possible to do the following either +from a Python script, or interactively from a Python prompt: create +one or more instances of LAMMPS, invoke LAMMPS commands or give it an +input script, run LAMMPS incrementally, extract LAMMPS results, an +modify internal LAMMPS variables. From a Python script you can do +this in serial or parallel. Running Python interactively in parallel +does not generally work, unless you have a version of Python that +extends standard Python to enable multiple instances of Python to read +what you type. + +To do all of this, you must first build LAMMPS as a shared library, +then insure that your Python can find the python/lammps.py file and +the shared library. These steps are explained in subsequent sections +11.3 and 11.4. Sections 11.5 and 11.6 discuss using MPI from a +parallel Python program and how to test that you are ready to use +LAMMPS from Python. Section 11.7 lists all the functions in the +current LAMMPS library interface and how to call them from Python. + +Section 11.8 gives some examples of coupling LAMMPS to other tools via +Python. For example, LAMMPS can easily be coupled to a GUI or other +visualization tools that display graphs or animations in real time as +LAMMPS runs. Examples of such scripts are inlcluded in the python +directory. + +Two advantages of using Python to run LAMMPS are how concise the +language is, and that it can be run interactively, enabling rapid +development and debugging of programs. If you use it to mostly invoke +costly operations within LAMMPS, such as running a simulation for a reasonable number of timesteps, then the overhead cost of invoking LAMMPS thru Python will be negligible. -Before using LAMMPS from a Python script, you need to do two things. -You need to build LAMMPS as a dynamic shared library, so it can be -loaded by Python. And you need to tell Python how to find the library -and the Python wrapper file python/lammps.py. Both these steps are -discussed below. If you wish to run LAMMPS in parallel from Python, -you also need to extend your Python with MPI. This is also discussed -below. - The Python wrapper for LAMMPS uses the amazing and magical (to me) "ctypes" package in Python, which auto-generates the interface code needed between Python and a set of C interface routines for a library. @@ -71,16 +107,78 @@ check which version of Python you have installed, by simply typing "python" at a shell prompt. :line + +11.2 Overview of using Python from a LAMMPS script :link(py_2),h4 + +LAMMPS has a "python"_python.html command which can be used in an +input script to define and execute a Python function that you write +the code for. The Python function can also be assigned to a LAMMPS +python-style variable via the "variable"_variable.html command. Each +time the variable is evaluated, either in the LAMMPS input script +itself, or by another LAMMPS command that uses the variable, this will +trigger the Python function to be invoked. + +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 +are mapped to LAMMPS variables (also defined in the input script) and +it can return a value to a LAMMPS variable. This is thus a mechanism +for your input script to pass information to a piece of Python code, +ask Python to execute the code, and return information to your input +script. + +Note that a Python function can be arbitrarily complex. It can import +other Python modules, instantiate Python classes, call other Python +functions, etc. The Python code that you provide can contain more +code than the single function. It can contain other functions or +Python classes, as well as global variables or other mechanisms for +storing state between calls from LAMMPS to the function. + +The Python function you provide can consist of "pure" Python code that +only performs operations provided by standard Python. However, the +Python function can also "call back" to LAMMPS through its +Python-wrapped library interface, in the manner described in the +previous section 11.1. This means it can issue LAMMPS input script +commands or query and set internal LAMMPS state. As an example, this +can be useful in an input script to create a more complex loop with +branching logic, than can be created using the simple looping and +brancing logic enabled by the "next"_next_html and "if"_if.html +commands. + +See the "python"_python.html doc page and the "variable"_variable.html +doc page for its python-style variables for more info, including +examples of Python code you can write for both pure Python operations +and callbacks to LAMMPS. + +To run pure Python code from LAMMPS, you only need to build LAMMPS +with the PYTHON package installed: + +make yes-python +make machine + +Note that this will link LAMMPS with the Python library on your +system, which typically requires several auxiliary system libraries to +also be linked. The list of these libraries and the paths to find +them are specified in the lib/python/Makefile.lammps file. You need +to insure that file contains the correct information for your version +of Python and your machine to successfully build LAMMPS. See the +lib/python/README file for more info. + +If you want to write Python code with callbacks to LAMMPS, then you +must also follow the steps overviewed in the preceeding section (11.1) +for running LAMMPS from Python. I.e. you must build LAMMPS as a +shared library and insure that Python can find the python/lammps.py +file and the shared library. + :line -11.1 Building LAMMPS as a shared library :link(py_1),h4 +11.3 Building LAMMPS as a shared library :link(py_3),h4 Instructions on how to build LAMMPS as a shared library are given in "Section_start 5"_Section_start.html#start_5. A shared library is one -that is dynamically loadable, which is what Python requires. On Linux -this is a library file that ends in ".so", not ".a". +that is dynamically loadable, which is what Python requires to wrap +LAMMPS. On Linux this is a library file that ends in ".so", not ".a". -From the src directory, type +>From the src directory, type make foo mode=shlib :pre @@ -98,7 +196,7 @@ system. :line -11.2 Installing the Python wrapper into Python :link(py_2),h4 +11.4 Installing the Python wrapper into Python :link(py_4),h4 For Python to invoke LAMMPS, there are 2 files it needs to know about: @@ -166,7 +264,7 @@ environment variable as described above. :line -11.3 Extending Python with MPI to run in parallel :link(py_3),h4 +11.5 Extending Python with MPI to run in parallel :link(py_5),h4 If you wish to run LAMMPS in parallel from Python, you need to extend your Python with an interface to MPI. This also allows you to @@ -193,11 +291,12 @@ believe) creates a new alternate executable (in place of "python" itself) as a result. In principle any of these Python/MPI packages should work to invoke -LAMMPS in parallel and MPI calls themselves from a Python script which -is itself running in parallel. However, when I downloaded and looked -at a few of them, their documentation was incomplete and I had trouble -with their installation. It's not clear if some of the packages are -still being actively developed and supported. +LAMMPS in parallel and to make MPI calls themselves from a Python +script which is itself running in parallel. However, when I +downloaded and looked at a few of them, their documentation was +incomplete and I had trouble with their installation. It's not clear +if some of the packages are still being actively developed and +supported. The one I recommend, since I have successfully used it with LAMMPS, is Pypar. Pypar requires the ubiquitous "Numpy @@ -257,7 +356,7 @@ the right one. :line -11.4 Testing the Python-LAMMPS interface :link(py_4),h4 +11.6 Testing the Python-LAMMPS interface :link(py_6),h4 To test if LAMMPS is callable from Python, launch Python interactively and type: @@ -370,22 +469,24 @@ Python on a single processor, not in parallel. :line :line -11.5 Using LAMMPS from Python :link(py_5),h4 +11.7 Using LAMMPS from Python :link(py_7),h4 -The Python interface to LAMMPS consists of a Python "lammps" module, -the source code for which is in python/lammps.py, which creates a -"lammps" object, with a set of methods that can be invoked on that -object. The sample Python code below assumes you have first imported -the "lammps" module in your Python script, as follows: +As described above, the Python interface to LAMMPS consists of a +Python "lammps" module, the source code for which is in +python/lammps.py, which creates a "lammps" object, with a set of +methods that can be invoked on that object. The sample Python code +below assumes you have first imported the "lammps" module in your +Python script, as follows: from lammps import lammps :pre -These are the methods defined by the lammps module. If you look -at the file src/library.cpp you will see that they correspond -one-to-one with calls you can make to the LAMMPS library from a C++ or -C or Fortran program. +These are the methods defined by the lammps module. If you look at +the files src/library.cpp and src/library.h you will see that they +correspond one-to-one with calls you can make to the LAMMPS library +from a C++ or C or Fortran program. lmp = lammps() # create a LAMMPS object using the default liblammps.so library +lmp = lammps(ptr=lmpptr) # ditto, but use lmpptr as previously created LAMMPS object lmp = lammps("g++") # create a LAMMPS object using the liblammps_g++.so library lmp = lammps("",list) # ditto, with command-line args, e.g. list = \["-echo","screen"\] lmp = lammps("g++",list) :pre @@ -444,6 +545,33 @@ processors. If someone figures out how to do this with one or more of the Python wrappers for MPI, like Pypar, please let us know and we will amend these doc pages. +The lines + +from lammps import lammps +lmp = lammps() :pre + +create an instance of LAMMPS, wrapped in a Python class by the lammps +Python module, and return an instance of the Python class as lmp. It +is used to make all subequent calls to the LAMMPS library. + +Additional arguments can be used to tell Python the name of the shared +library to load or to pass arguments to the LAMMPS instance, the same +as if LAMMPS were launched from a command-line prompt. + +If the ptr argument is set like this: + +lmp = lammps(ptr=lmpptr) :pre + +then lmpptr must be an argument passed to Python via the LAMMPS +"python"_python.html command, when it is used to define a Python +function that is invoked by the LAMMPS input script. This mode of +using Python with LAMMPS is described above in 11.2. The variable +lmpptr refers to the instance of LAMMPS that called the embedded +Python interpreter. Using it as an argument to lammps() allows the +returned Python class instance "lmp" to make calls to that instance of +LAMMPS. See the "python"_python.html command doc page for examples +using this syntax. + Note that you can create multiple LAMMPS objects in your Python script, and coordinate and run multiple simulations, e.g. @@ -572,7 +700,7 @@ Python script. Isn't ctypes amazing? :l,ule :line :line -11.6 Example Python scripts that use LAMMPS :link(py_6),h4 +11.8 Example Python scripts that use LAMMPS :link(py_8),h4 These are the Python scripts included as demos in the python/examples directory of the LAMMPS distribution, to illustrate the kinds of diff --git a/doc/Section_start.html b/doc/Section_start.html index b81fbc11c2..50f408a257 100644 --- a/doc/Section_start.html +++ b/doc/Section_start.html @@ -171,7 +171,7 @@ all good starting points if you find you need to change them for your machine. Put any file you edit into the src/MAKE/MINE directory and it will be never be touched by any LAMMPS updates.
-From within the src directory, type "make" or "gmake". You should see +
>From within the src directory, type "make" or "gmake". You should see a list of available choices from src/MAKE and all of its sub-directories. If one of those has the options you want or is the machine you want, you can type a command like: @@ -772,20 +772,30 @@ options. Packages that require extra libraries:
A few of the standard and user packages require additional auxiliary -libraries. They must be compiled first, before LAMMPS is built. If -you get a LAMMPS build error about a missing library, this is likely -the reason. See the Section_packages doc page -for a list of packages that have auxiliary libraries. +libraries. Most of them are provided with LAMMPS, in which case they +must be compiled first, before LAMMPS is built if you wish to include +that package. If you get a LAMMPS build error about a missing +library, this is likely the reason. See the +Section_packages doc page for a list of +packages that have these kinds of auxiliary libraries.
The lib directory in the distribution has sub-directories with package -names that correspond to the needed auxiliary libs, e.g. lib/reax. +names that correspond to the needed auxiliary libs, e.g. lib/reax. Each sub-directory has a README file that gives more details. Code for most of the auxiliary libraries is included in that directory. -Examples are the USER-ATC and MEAM packages. A few of the -sub-directories do not include code, but do include instructions and -sometimes scripts that automate the process of downloading the -auxiliary library and installing it so LAMMPS can link to it. -Examples are the KIM and VORONOI and USER-MOLFILE packages. +Examples are the USER-ATC and MEAM packages. +
+A few of the lib sub-directories do not include code, but do include +instructions and sometimes scripts that automate the process of +downloading the auxiliary library and installing it so LAMMPS can link +to it. Examples are the KIM and VORONOI and USER-MOLFILE packages. +
+The lib/python directory (for the PYTHON package) contains only a +choice of Makefile.lammps.* files. This is because no auxiliary code +or libraries are needed, only the Python library and other system libs +that already available on your system. However, the Makefile.lammps +file is needed to tell the LAMMPS build which libs to use and where to +find them.
For libraries with provided code, the sub-directory README file (e.g. lib/reax/README) has instructions on how to build that library. diff --git a/doc/Section_start.txt b/doc/Section_start.txt index e89ec84a6c..571b3e53f1 100644 --- a/doc/Section_start.txt +++ b/doc/Section_start.txt @@ -165,7 +165,7 @@ all good starting points if you find you need to change them for your machine. Put any file you edit into the src/MAKE/MINE directory and it will be never be touched by any LAMMPS updates. -From within the src directory, type "make" or "gmake". You should see +>From within the src directory, type "make" or "gmake". You should see a list of available choices from src/MAKE and all of its sub-directories. If one of those has the options you want or is the machine you want, you can type a command like: @@ -766,20 +766,30 @@ options. [{Packages that require extra libraries:}] :link(start_3_3) A few of the standard and user packages require additional auxiliary -libraries. They must be compiled first, before LAMMPS is built. If -you get a LAMMPS build error about a missing library, this is likely -the reason. See the "Section_packages"_Section_packages.html doc page -for a list of packages that have auxiliary libraries. +libraries. Most of them are provided with LAMMPS, in which case they +must be compiled first, before LAMMPS is built if you wish to include +that package. If you get a LAMMPS build error about a missing +library, this is likely the reason. See the +"Section_packages"_Section_packages.html doc page for a list of +packages that have these kinds of auxiliary libraries. The lib directory in the distribution has sub-directories with package -names that correspond to the needed auxiliary libs, e.g. lib/reax. +names that correspond to the needed auxiliary libs, e.g. lib/reax. Each sub-directory has a README file that gives more details. Code for most of the auxiliary libraries is included in that directory. -Examples are the USER-ATC and MEAM packages. A few of the -sub-directories do not include code, but do include instructions and -sometimes scripts that automate the process of downloading the -auxiliary library and installing it so LAMMPS can link to it. -Examples are the KIM and VORONOI and USER-MOLFILE packages. +Examples are the USER-ATC and MEAM packages. + +A few of the lib sub-directories do not include code, but do include +instructions and sometimes scripts that automate the process of +downloading the auxiliary library and installing it so LAMMPS can link +to it. Examples are the KIM and VORONOI and USER-MOLFILE packages. + +The lib/python directory (for the PYTHON package) contains only a +choice of Makefile.lammps.* files. This is because no auxiliary code +or libraries are needed, only the Python library and other system libs +that already available on your system. However, the Makefile.lammps +file is needed to tell the LAMMPS build which libs to use and where to +find them. For libraries with provided code, the sub-directory README file (e.g. lib/reax/README) has instructions on how to build that library. diff --git a/doc/print.html b/doc/print.html index 3b868c860a..e97b5e2188 100644 --- a/doc/print.html +++ b/doc/print.html @@ -13,8 +13,8 @@
Syntax:
-print string keyword value:pre -
+print string keyword value +
print "Done with equilibration" file info.dat print Vol=$v append info.dat screen no print "The system volume is now $v" -print 'The system volume is now $v' +print 'The system volume is now $v' +print """ +System volume = $v +System temperature = $t +"""
Description:
-Print a text string to the screen and logfile. One line of output is -generated. The text string must be a single argument, so it should be -enclosed in double quotes if it is more than one word. If it contains -variables, they will be evaluated and their current values printed. +
Print a text string to the screen and logfile. The text string must +be a single argument, so if it is one line but more than one word, it +should be enclosed in single or double quotes. To generate multiple +lines of output, the string can be enclosed in triple quotes, as in +the last example above. If the text string contains variables, they +will be evaluated and their current values printed.
If the file or append keyword is used, a filename is specified to which the output will be written. If file is used, then the diff --git a/doc/print.txt b/doc/print.txt index e69c70e194..a76440b87d 100644 --- a/doc/print.txt +++ b/doc/print.txt @@ -10,7 +10,7 @@ print command :h3 [Syntax:] -print string keyword value:pre +print string keyword value :pre string = text string to print, which may contain variables :ulb,l zero or more keyword/value pairs may be appended :l @@ -25,14 +25,20 @@ keyword = {file} or {append} or {screen} :l print "Done with equilibration" file info.dat print Vol=$v append info.dat screen no print "The system volume is now $v" -print 'The system volume is now $v' :pre +print 'The system volume is now $v' +print """ +System volume = $v +System temperature = $t +""" :pre [Description:] -Print a text string to the screen and logfile. One line of output is -generated. The text string must be a single argument, so it should be -enclosed in double quotes if it is more than one word. If it contains -variables, they will be evaluated and their current values printed. +Print a text string to the screen and logfile. The text string must +be a single argument, so if it is one line but more than one word, it +should be enclosed in single or double quotes. To generate multiple +lines of output, the string can be enclosed in triple quotes, as in +the last example above. If the text string contains variables, they +will be evaluated and their current values printed. If the {file} or {append} keyword is used, a filename is specified to which the output will be written. If {file} is used, then the @@ -69,4 +75,3 @@ thermodynamic properties, global values calculated by a [Default:] The option defaults are no file output and screen = yes. - diff --git a/doc/python.html b/doc/python.html new file mode 100644 index 0000000000..caea4dfe96 --- /dev/null +++ b/doc/python.html @@ -0,0 +1,485 @@ + +
Syntax: +
+python func keyword args ... ++
keyword = invoke or input or return or format or file or here or exists + 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 + return arg = varReturn + varReturn = v_name = LAMMPS variable name which return value of 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 + file arg = filename + filename = file of Python code, which defines func + here arg = inline + inline = one or more lines of Python code which defines func + must be a single argument, typically enclosed between triple quotes + exists arg = none = Python code has been loaded by previous python command ++ +
Examples: +
+python pForce input 2 v_x 20.0 return v_f format fff file force.py +python pForce invoke ++
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 -f 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") + """ ++
Description: +
+Define a Python function or execute a previously defined function. +Arguments, including LAMMPS variables, can be passed to the function +from the LAMMPS input script and a value returned by the Python +function 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. +
+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 +defined. One is using the invoke keyword. The other is to assign +the function to a python-style 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 for 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 Section python. There is an +examples/python directory which illustrates use of the python +command. +
+The func setting specifies the name of the Python function. The +code for the function is defined using the file or here keywords +as explained below. +
+If the invoke keyword is used, no other keywords can be used, and a +previous python command must have defined the Python function +referenced by this command. This invokes the Python function with the +previously defined arguments and return value processed as explained +below. You can invoke the 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 converts into a reference to LAMMPS +itself. 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 can be used, as defined +by the variable command. Each time the Python +function is invoked, the LAMMPS variable is evaluated and its value is +passed to the Python function. +
+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 +variable command. The Python function can return a +numeric or string value, as specified by the format keyword. +
+As explained on the variable doc page, the definition +of a python-style variable associates a Python function name with the +variable. This must match the func setting for this command. For +exampe these two commands would be self-consistent: +
+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 keyword +is 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 python-style +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. +
+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, +which should end with a ".py" suffix, which contains Python code. The +code will be immediately loaded into and run in the "main" module of +the Python interpreter. 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 +Section 3.2, 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 defined by the func setting, +is assumed to have been previously loaded by another python command. +
+Note that the Python code that is loaded and run must contain a +function with the specified func name. To operate properly when +later invoked, the 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. __main__. The code can +define global variables or 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 access +the other functions previously loaded. +
+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: +
+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 ++
Nsteplast stores the previous timestep the function was invoked +(passed as an argument to the function). 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. +
+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 statement 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. Welcome to the world of parallel programming and +debugging. +
+Second, if your Python code loads 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 insure all your Python +functions (running independently on different processors) call back to +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: +
+def foo(lmpptr,...): + from lammps import lammps + lmp = lammps(ptr=lmpptr) + lmp.command('print "Hello from inside Python"') + ... ++
The function definition must include a variable (lmpptr in this case) +which corresponds to SELF in the python command. The first line of +the function imports the Python module lammps.py in the python dir of +the distribution. The second line creates a Python object "lmp" which +wraps the instance of LAMMPS that called the function. The +"ptr=lmpptr" argument is what makes that happen. The thrid 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 +
+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. +
+Section 11.7 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: +
+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) # LAMMPS command option ++
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: +
+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 threshhold 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 +jump and 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 "LAMMPS command option" line could be used +in place of the 2 preceeding lines, to have Python insert the value +into the LAMMPS command string. +
+IMPORTANT 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. +
+However, a Python function can also be invoked during a run, whenever +an associated LAMMPS variable it is assigned to is evaluted. If the +variable is an input argument to another LAMMPS command (e.g. 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. +
+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: +
+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: +
+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: +
+foo += 1 ++
If you put one (or more) statements inside a "try" statement, +like this: +
+import exceptions +print "Inside simple function" +try: + foo += 1 # one or more statements here +except Exception, e: + print "FOO error:",e ++
then you will get this message printed to the screen: +
+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 Making +LAMMPS section 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 to load the Python module in +python/lammps.py 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 in Section +python. 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. +
+As described above, you can use the python command to invoke a Python +function which calls back to LAMMPS through its Python-wrapped library +interface. However you cannot do the opposite. I.e. you cannot call +LAMMPS from Python and invoke the python command to "callback" to +Python and execute a Python function. LAMMPS will generate an error +if you try to do that. Note that we think there actually should be a +way to do that, but haven't yet been able to figure out how to do it +successfully. +
+Related commands: +
+ +Default: none +
+ diff --git a/doc/python.txt b/doc/python.txt new file mode 100644 index 0000000000..6843f4e428 --- /dev/null +++ b/doc/python.txt @@ -0,0 +1,477 @@ +"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c + +:link(lws,http://lammps.sandia.gov) +:link(ld,Manual.html) +:link(lc,Section_commands.html#comm) + +:line + +python command :h3 + +[Syntax:] + +python func keyword args ... :pre + +func = name of Python function :ulb,l +one or more keyword/args pairs must be appended :l +keyword = {invoke} or {input} or {return} or {format} or {file} or {here} or {exists} + {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 + {return} arg = varReturn + varReturn = v_name = LAMMPS variable name which return value of 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 + {file} arg = filename + filename = file of Python code, which defines func + {here} arg = inline + inline = one or more lines of Python code which defines func + must be a single argument, typically enclosed between triple quotes + {exists} arg = none = Python code has been loaded by previous python command :pre +:ule + +[Examples:] + +python pForce input 2 v_x 20.0 return v_f format fff file force.py +python pForce invoke :pre + +python factorial input 1 myN return v_fac format ii here """ +def factorial(n): + if n == 1: return n + return n * factorial(n-1) + """ :pre + +python loop input 1 SELF return v_value format -f here """ +def loop(lmpptr,N,cut0): + from lammps import lammps + lmp = lammps(ptr=lmpptr) :pre + + # loop N times, increasing cutoff each time :pre + + 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") + """ :pre + +[Description:] + +Define a Python function or execute a previously defined function. +Arguments, including LAMMPS variables, can be passed to the function +from the LAMMPS input script and a value returned by the Python +function 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. + +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 +defined. One is using the {invoke} keyword. The other is to assign +the function to a "python-style variable"_variable.html 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 for 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 "Section python"_Section_python.html. There is an +examples/python directory which illustrates use of the python +command. + +:line + +The {func} setting specifies the name of the Python function. The +code for the function is defined using the {file} or {here} keywords +as explained below. + +If the {invoke} keyword is used, no other keywords can be used, and a +previous python command must have defined the Python function +referenced by this command. This invokes the Python function with the +previously defined arguments and return value processed as explained +below. You can invoke the 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 converts into a reference to LAMMPS +itself. 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 can be used, as defined +by the "variable"_variable.html command. Each time the Python +function is invoked, the LAMMPS variable is evaluated and its value is +passed to the Python function. + +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 +"variable"_variable.html command. The Python function can return a +numeric or string value, as specified by the {format} keyword. + +As explained on the "variable"_variable.html doc page, the definition +of a python-style variable associates a Python function name with the +variable. This must match the {func} setting for this command. For +exampe these two commands would be self-consistent: + +variable foo python myMultiply +python myMultiply return v_foo format f file funcs.py :pre + +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} keyword +is 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 "python-style +variable"_variable.html 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. + +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, +which should end with a ".py" suffix, which contains Python code. The +code will be immediately loaded into and run in the "main" module of +the Python interpreter. 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 +"Section 3.2"_Section_commands.html#cmd_2, 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 defined by the {func} setting, +is assumed to have been previously loaded by another python command. + +Note that the Python code that is loaded and run must contain a +function with the specified {func} name. To operate properly when +later invoked, the the function code must match the {input} and +{return} and {format} keywords specified by the python command. +Otherwise Python will generate an error. + +:line + +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. __main__. The code can +define global variables or 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 access +the other functions previously loaded. + +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: + +nsteplast = -1 +nvaluelast = 0 :pre + +def expensive(nstep): + global nsteplast,nvaluelast + if nstep == nsteplast: return nvaluelast + nsteplast = nstep + # perform complicated calculation + nvalue = ... + nvaluelast = nvalue + return nvalue :pre + +Nsteplast stores the previous timestep the function was invoked +(passed as an argument to the function). 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. + +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 statement 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. Welcome to the world of parallel programming and +debugging. + +Second, if your Python code loads 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 insure all your Python +functions (running independently on different processors) call back to +LAMMPS. Otherwise the code may hang. + +:line + +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: + +def foo(lmpptr,...): + from lammps import lammps + lmp = lammps(ptr=lmpptr) + lmp.command('print "Hello from inside Python"') + ... :pre + +The function definition must include a variable (lmpptr in this case) +which corresponds to SELF in the python command. The first line of +the function imports the Python module lammps.py in the python dir of +the distribution. The second line creates a Python object "lmp" which +wraps the instance of LAMMPS that called the function. The +"ptr=lmpptr" argument is what makes that happen. The thrid 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 + +Hello from inside Python :pre + +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. + +"Section 11.7"_Section_python.html#py_7 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: + +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() :pre + + for i in range(N): + cut = cut0 + i*0.1 :pre + + 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 :pre + + 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 :pre + +with these input script commands: + +python loop input 4 10 1.0 -4.0 SELF format iffp file funcs.py +python loop invoke :pre + +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 threshhold 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 +"jump"_jump.html and "if"_if.html 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 "LAMMPS command option" line could be used +in place of the 2 preceeding lines, to have Python insert the value +into the LAMMPS command string. + +IMPORTANT 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. + +However, a Python function can also be invoked during a run, whenever +an associated LAMMPS variable it is assigned to is evaluted. If the +variable is an input argument to another LAMMPS command (e.g. "fix +setforce"_fix_setforce.html), 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. + +:line + +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: + +Could not process Python file +Could not process Python string :pre + +When the Python function is invoked, if it does not return properly, +you will typically get this generic error from LAMMPS: + +Python function evaluation failed :pre + +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: + +foo += 1 :pre + +If you put one (or more) statements inside a "try" statement, +like this: + +import exceptions +print "Inside simple function" +try: + foo += 1 # one or more statements here +except Exception, e: + print "FOO error:",e :pre + +then you will get this message printed to the screen: + +FOO error: local variable 'foo' referenced before assignment :pre + +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). + +:line + +[Restrictions:] + +This command is part of the PYTHON package. It is only enabled if +LAMMPS was built with that package. See the "Making +LAMMPS"_Section_start.html#start_3 section 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 to load the Python module in +python/lammps.py 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 in "Section +python"_Section.python.html. 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. + +As described above, you can use the python command to invoke a Python +function which calls back to LAMMPS through its Python-wrapped library +interface. However you cannot do the opposite. I.e. you cannot call +LAMMPS from Python and invoke the python command to "callback" to +Python and execute a Python function. LAMMPS will generate an error +if you try to do that. Note that we think there actually should be a +way to do that, but haven't yet been able to figure out how to do it +successfully. + +[Related commands:] + +"shell"_shell.html, "variable"_variable.html + +[Default:] none diff --git a/doc/variable.html b/doc/variable.html index 867744dc42..cf8e5d66ea 100644 --- a/doc/variable.html +++ b/doc/variable.html @@ -17,7 +17,8 @@delete = no args index args = one or more strings @@ -45,6 +46,7 @@ getenv arg = one string file arg = filename atomfile arg = filename + python arg = function equal or atom args = one formula containing numbers, thermo keywords, math operations, group functions, atom values and vectors, compute/fix/variable references numbers = 0.0, 100, -5.4, 2.8e-4, etc constants = PI @@ -87,6 +89,7 @@ variable b equal xcm(mol1,x)/2.0 variable b equal c_myTemp variable b atom x*y/vol variable foo string myfile +variable myPy python increase variable f file values.txt variable temp world 300.0 310.0 320.0 ${Tfinal} variable x universe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @@ -116,7 +119,9 @@ command) or used as input to an averaging fix (see the fix ave/atom commands). Variables of style atomfile can be used anywhere in an input script that atom-style variables are used; they get their -per-atom values from a file rather than from a formula. +per-atom values from a file rather than from a formula. Variables can +be hooked to Python functions using code you provide, so that the +variable gets its value from the evaluation of the Python code.IMPORTANT NOTE: As discussed in Section 3.2 of the manual, an input script can @@ -138,11 +143,31 @@ different values when it is evaluated at different times during a simulation.
IMPORTANT NOTE: When the input script line is encountered that defines -a variable of style equal or atom that contains a formula, the -formula is NOT immediately evaluated and the result stored. See the -discussion below about "Immediate Evaluation of Variables" if you want -to do this. This is also true of the format style variable -since it evaluates another variable when it is invoked. +a variable of style equal or atom or python that contains a +formula or Python code, the formula is NOT immediately evaluated and +the result stored. See the discussion below about "Immediate +Evaluation of Variables" if you want to do this. This is also true of +the format style variable since it evaluates another variable when +it is invoked. +
+IMPORTANT NOTE: Variables of style equal and atom can be used as +inputs to various other LAMMPS commands which evaluate their formulas +as needed, e.g. at different timesteps during a run. +Variables of style python can be used in place of an equal-style +variable so long as the associated Python function, as defined by the +python command, returns a numeric value. Thus any +command that states it can use an equal-style variable as an argument, +can also use such a python-style variable. This means that when the +LAMMPS command evaluates the variable, the Python function will be +executed. +
+When the input script line is encountered that defines +a variable of style equal or atom or python that contains a +formula or Python code, the formula is NOT immediately evaluated and +the result stored. See the discussion below about "Immediate +Evaluation of Variables" if you want to do this. This is also true of +the format style variable since it evaluates another variable when +it is invoked.
IMPORTANT NOTE: When a variable command is encountered in the input script and the variable name has already been specified, the command @@ -155,12 +180,12 @@ means that using the command-line switch< script.
There are two exceptions to this rule. First, variables of style -string, getenv, equal and atom ARE redefined each time the -command is encountered. This allows these style of variables to be -redefined multiple times in an input script. In a loop, this means -the formula associated with an equal or atom style variable can -change if it contains a substitution for another variable, e.g. $x or -v_x. +string, getenv, equal, atom, and python ARE redefined each +time the command is encountered. This allows these style of variables +to be redefined multiple times in an input script. In a loop, this +means the formula associated with an equal or atom style variable +can change if it contains a substitution for another variable, e.g. $x +or v_x.
Second, as described below, if a variable is iterated on to the end of its list of strings via the next command, it is removed @@ -202,13 +227,15 @@ variable a delete
This section describes how various variable styles are defined and -what they store. Many of the styles store one or more strings. Note -that a single string can contain spaces (multiple words), if it is -enclosed in quotes in the variable command. When the variable is -substituted for in another input script command, its returned string -will then be interpreted as multiple arguments in the expanded -command. +
This section describes how all the various variable styles are defined +and what they store. Except for the equal and atom styles, +which are explaine in the next section. +
+Many of the styles store one or more strings. Note that a single +string can contain spaces (multiple words), if it is enclosed in +quotes in the variable command. When the variable is substituted for +in another input script command, its returned string will then be +interpreted as multiple arguments in the expanded command.
For the index style, one or more strings are specified. Initially, the 1st string is assigned to the variable. Each time a @@ -338,6 +365,31 @@ will be assigned to that atom. IDs can be listed in any order. for all atoms is first set to 0.0. Thus values for atoms whose ID does not appear in the set, will remain 0.0.
+For the python style a Python function name is provided. This needs +to match a function name specified in a python command +which returns a value to this variable as defined by its return +keyword. For exampe these two commands would be self-consistent: +
+variable foo python myMultiply +python myMultiply return v_foo format f file funcs.py ++
The two commands can appear in either order so long as both are +specified before the Python function is invoked for the first time. +
+Each time the variable is evaluated, the associated Python function is +invoked, and the value it returns is also returned by the variable. +Since the Python function can use other LAMMPS variables as input, or +query interal LAMMPS quantities to perform its computation, this means +the variable can return a different value each time it is evaluated. +
+The type of value stored in the variable is determined by the format +keyword of the python command. It can be an integer +(i), floating point (f), or string (s) value. As mentioned above, if +it is a numeric value (integer or floating point), then the +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 +that allows for equal-style variables. +
For the equal and atom styles, a single string is specified which diff --git a/doc/variable.txt b/doc/variable.txt index 1655b4269e..f79e5cd580 100644 --- a/doc/variable.txt +++ b/doc/variable.txt @@ -13,7 +13,8 @@ variable command :h3 variable name style args ... :pre name = name of variable to define :ulb,l -style = {delete} or {index} or {loop} or {world} or {universe} or {uloop} or {string} or {format} or {getenv} or {file} or {atomfile} or {equal} or {atom} :l +style = {delete} or {index} or {loop} or {world} or {universe} or +{uloop} or {string} or {format} or {getenv} or {file} or {atomfile} or {python} or {equal} or {atom} :l {delete} = no args {index} args = one or more strings {loop} args = N @@ -40,6 +41,7 @@ style = {delete} or {index} or {loop} or {world} or {universe} or {uloop} or {st {getenv} arg = one string {file} arg = filename {atomfile} arg = filename + {python} arg = function {equal} or {atom} args = one formula containing numbers, thermo keywords, math operations, group functions, atom values and vectors, compute/fix/variable references numbers = 0.0, 100, -5.4, 2.8e-4, etc constants = PI @@ -81,6 +83,7 @@ variable b equal xcm(mol1,x)/2.0 variable b equal c_myTemp variable b atom x*y/vol variable foo string myfile +variable myPy python increase variable f file values.txt variable temp world 300.0 310.0 320.0 $\{Tfinal\} variable x universe 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @@ -110,7 +113,9 @@ command) or used as input to an averaging fix (see the "fix ave/spatial"_fix_ave_spatial.html and "fix ave/atom"_fix_ave_atom.html commands). Variables of style {atomfile} can be used anywhere in an input script that atom-style variables are used; they get their -per-atom values from a file rather than from a formula. +per-atom values from a file rather than from a formula. Variables can +be hooked to Python functions using code you provide, so that the +variable gets its value from the evaluation of the Python code. IMPORTANT NOTE: As discussed in "Section 3.2"_Section_commands.html#cmd_2 of the manual, an input script can @@ -132,11 +137,31 @@ different values when it is evaluated at different times during a simulation. IMPORTANT NOTE: When the input script line is encountered that defines -a variable of style {equal} or {atom} that contains a formula, the -formula is NOT immediately evaluated and the result stored. See the -discussion below about "Immediate Evaluation of Variables" if you want -to do this. This is also true of the {format} style variable -since it evaluates another variable when it is invoked. +a variable of style {equal} or {atom} or {python} that contains a +formula or Python code, the formula is NOT immediately evaluated and +the result stored. See the discussion below about "Immediate +Evaluation of Variables" if you want to do this. This is also true of +the {format} style variable since it evaluates another variable when +it is invoked. + +IMPORTANT NOTE: Variables of style {equal} and {atom} can be used as +inputs to various other LAMMPS commands which evaluate their formulas +as needed, e.g. at different timesteps during a "run"_run.html. +Variables of style {python} can be used in place of an equal-style +variable so long as the associated Python function, as defined by the +"python"_python.html command, returns a numeric value. Thus any +command that states it can use an equal-style variable as an argument, +can also use such a python-style variable. This means that when the +LAMMPS command evaluates the variable, the Python function will be +executed. + +When the input script line is encountered that defines +a variable of style {equal} or {atom} or {python} that contains a +formula or Python code, the formula is NOT immediately evaluated and +the result stored. See the discussion below about "Immediate +Evaluation of Variables" if you want to do this. This is also true of +the {format} style variable since it evaluates another variable when +it is invoked. IMPORTANT NOTE: When a variable command is encountered in the input script and the variable name has already been specified, the command @@ -149,12 +174,12 @@ means that using the "command-line switch"_Section_start.html#start_7 script. There are two exceptions to this rule. First, variables of style -{string}, {getenv}, {equal} and {atom} ARE redefined each time the -command is encountered. This allows these style of variables to be -redefined multiple times in an input script. In a loop, this means -the formula associated with an {equal} or {atom} style variable can -change if it contains a substitution for another variable, e.g. $x or -v_x. +{string}, {getenv}, {equal}, {atom}, and {python} ARE redefined each +time the command is encountered. This allows these style of variables +to be redefined multiple times in an input script. In a loop, this +means the formula associated with an {equal} or {atom} style variable +can change if it contains a substitution for another variable, e.g. $x +or v_x. Second, as described below, if a variable is iterated on to the end of its list of strings via the "next"_next.html command, it is removed @@ -196,13 +221,15 @@ variable a delete :pre :line -This section describes how various variable styles are defined and -what they store. Many of the styles store one or more strings. Note -that a single string can contain spaces (multiple words), if it is -enclosed in quotes in the variable command. When the variable is -substituted for in another input script command, its returned string -will then be interpreted as multiple arguments in the expanded -command. +This section describes how all the various variable styles are defined +and what they store. Except for the {equal} and {atom} styles, +which are explaine in the next section. + +Many of the styles store one or more strings. Note that a single +string can contain spaces (multiple words), if it is enclosed in +quotes in the variable command. When the variable is substituted for +in another input script command, its returned string will then be +interpreted as multiple arguments in the expanded command. For the {index} style, one or more strings are specified. Initially, the 1st string is assigned to the variable. Each time a @@ -332,6 +359,31 @@ IMPORTANT NOTE: Every time a set of per-atom lines is read, the value for all atoms is first set to 0.0. Thus values for atoms whose ID does not appear in the set, will remain 0.0. +For the {python} style a Python function name is provided. This needs +to match a function name specified in a "python"_python.html command +which returns a value to this variable as defined by its {return} +keyword. For exampe these two commands would be self-consistent: + +variable foo python myMultiply +python myMultiply return v_foo format f file funcs.py :pre + +The two commands can appear in either order so long as both are +specified before the Python function is invoked for the first time. + +Each time the variable is evaluated, the associated Python function is +invoked, and the value it returns is also returned by the variable. +Since the Python function can use other LAMMPS variables as input, or +query interal LAMMPS quantities to perform its computation, this means +the variable can return a different value each time it is evaluated. + +The type of value stored in the variable is determined by the {format} +keyword of the "python"_python.html command. It can be an integer +(i), floating point (f), or string (s) value. As mentioned above, if +it is a numeric value (integer or floating point), then the +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 +that allows for equal-style variables. + :line For the {equal} and {atom} styles, a single string is specified which