forked from lijiext/lammps
660 lines
28 KiB
HTML
660 lines
28 KiB
HTML
<HTML>
|
|
<CENTER><A HREF = "Section_modify.html">Previous Section</A> - <A HREF = "http://lammps.sandia.gov">LAMMPS WWW Site</A> - <A HREF = "Manual.html">LAMMPS Documentation</A> - <A HREF = "Section_commands.html#comm">LAMMPS Commands</A> - <A HREF = "Section_errors.html">Next Section</A>
|
|
</CENTER>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<HR>
|
|
|
|
<H3>11. Python interface to LAMMPS
|
|
</H3>
|
|
<P>This section describes how to build and use LAMMPS via a Python
|
|
interface.
|
|
</P>
|
|
<UL><LI>11.1 <A HREF = "#py_1">Building LAMMPS as a shared library</A>
|
|
<LI>11.2 <A HREF = "#py_2">Installing the Python wrapper into Python</A>
|
|
<LI>11.3 <A HREF = "#py_3">Extending Python with MPI to run in parallel</A>
|
|
<LI>11.4 <A HREF = "#py_4">Testing the Python-LAMMPS interface</A>
|
|
<LI>11.5 <A HREF = "#py_5">Using LAMMPS from Python</A>
|
|
<LI>11.6 <A HREF = "#py_6">Example Python scripts that use LAMMPS</A>
|
|
</UL>
|
|
<P>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.
|
|
</P>
|
|
<P><A HREF = "http://www.python.org">Python</A> 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 <A HREF = "Section_howto.html#howto_10">Section
|
|
section</A> of the manual and the couple
|
|
directory of the distribution for more ideas about coupling LAMMPS to
|
|
other codes. See <A HREF = "Section_start.html#start_5">Section_start 4</A> about
|
|
how to build LAMMPS as a library, and <A HREF = "Section_howto.html#howto_19">Section_howto
|
|
19</A> 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.
|
|
</P>
|
|
<P>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.
|
|
</P>
|
|
<P>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
|
|
reasonable number of timesteps, then the overhead cost of invoking
|
|
LAMMPS thru Python will be negligible.
|
|
</P>
|
|
<P>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.
|
|
</P>
|
|
<P>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.
|
|
Ctypes is part of standard Python for versions 2.5 and later. You can
|
|
check which version of Python you have installed, by simply typing
|
|
"python" at a shell prompt.
|
|
</P>
|
|
<HR>
|
|
|
|
<HR>
|
|
|
|
<A NAME = "py_1"></A><H4>11.1 Building LAMMPS as a shared library
|
|
</H4>
|
|
<P>Instructions on how to build LAMMPS as a shared library are given in
|
|
<A HREF = "Section_start.html#start_5">Section_start 5</A>. 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".
|
|
</P>
|
|
<P>From the src directory, type
|
|
</P>
|
|
<PRE>make makeshlib
|
|
make -f Makefile.shlib foo
|
|
</PRE>
|
|
<P>where foo is the machine target name, such as linux or g++ or serial.
|
|
This should create the file liblammps_foo.so in the src directory, as
|
|
well as a soft link liblammps.so, which is what the Python wrapper will
|
|
load by default. Note that if you are building multiple machine
|
|
versions of the shared library, the soft link is always set to the
|
|
most recently built version.
|
|
</P>
|
|
<P>If this fails, see <A HREF = "Section_start.html#start_5">Section_start 5</A> for
|
|
more details, especially if your LAMMPS build uses auxiliary libraries
|
|
like MPI or FFTW which may not be built as shared libraries on your
|
|
system.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_2"></A><H4>11.2 Installing the Python wrapper into Python
|
|
</H4>
|
|
<P>For Python to invoke LAMMPS, there are 2 files it needs to know about:
|
|
</P>
|
|
<UL><LI>python/lammps.py
|
|
<LI>src/liblammps.so
|
|
</UL>
|
|
<P>Lammps.py is the Python wrapper on the LAMMPS library interface.
|
|
Liblammps.so is the shared LAMMPS library that Python loads, as
|
|
described above.
|
|
</P>
|
|
<P>You can insure Python can find these files in one of two ways:
|
|
</P>
|
|
<UL><LI>set two environment variables
|
|
<LI>run the python/install.py script
|
|
</UL>
|
|
<P>If you set the paths to these files as environment variables, you only
|
|
have to do it once. For the csh or tcsh shells, add something like
|
|
this to your ~/.cshrc file, one line for each of the two files:
|
|
</P>
|
|
<PRE>setenv PYTHONPATH $<I>PYTHONPATH</I>:/home/sjplimp/lammps/python
|
|
setenv LD_LIBRARY_PATH $<I>LD_LIBRARY_PATH</I>:/home/sjplimp/lammps/src
|
|
</PRE>
|
|
<P>If you use the python/install.py script, you need to invoke it every
|
|
time you rebuild LAMMPS (as a shared library) or make changes to the
|
|
python/lammps.py file.
|
|
</P>
|
|
<P>You can invoke install.py from the python directory as
|
|
</P>
|
|
<PRE>% python install.py [libdir] [pydir]
|
|
</PRE>
|
|
<P>The optional libdir is where to copy the LAMMPS shared library to; the
|
|
default is /usr/local/lib. The optional pydir is where to copy the
|
|
lammps.py file to; the default is the site-packages directory of the
|
|
version of Python that is running the install script.
|
|
</P>
|
|
<P>Note that libdir must be a location that is in your default
|
|
LD_LIBRARY_PATH, like /usr/local/lib or /usr/lib. And pydir must be a
|
|
location that Python looks in by default for imported modules, like
|
|
its site-packages dir. If you want to copy these files to
|
|
non-standard locations, such as within your own user space, you will
|
|
need to set your PYTHONPATH and LD_LIBRARY_PATH environment variables
|
|
accordingly, as above.
|
|
</P>
|
|
<P>If the install.py script does not allow you to copy files into system
|
|
directories, prefix the python command with "sudo". If you do this,
|
|
make sure that the Python that root runs is the same as the Python you
|
|
run. E.g. you may need to do something like
|
|
</P>
|
|
<PRE>% sudo /usr/local/bin/python install.py [libdir] [pydir]
|
|
</PRE>
|
|
<P>You can also invoke install.py from the make command in the src
|
|
directory as
|
|
</P>
|
|
<PRE>% make install-python
|
|
</PRE>
|
|
<P>In this mode you cannot append optional arguments. Again, you may
|
|
need to prefix this with "sudo". In this mode you cannot control
|
|
which Python is invoked by root.
|
|
</P>
|
|
<P>Note that if you want Python to be able to load different versions of
|
|
the LAMMPS shared library (see <A HREF = "#py_5">this section</A> below), you will
|
|
need to manually copy files like lmplammps_g++.so into the appropriate
|
|
system directory. This is not needed if you set the LD_LIBRARY_PATH
|
|
environment variable as described above.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_3"></A><H4>11.3 Extending Python with MPI to run in parallel
|
|
</H4>
|
|
<P>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
|
|
make MPI calls directly from Python in your script, if you desire.
|
|
</P>
|
|
<P>There are several Python packages available that purport to wrap MPI
|
|
as a library and allow MPI functions to be called from Python.
|
|
</P>
|
|
<P>These include
|
|
</P>
|
|
<UL><LI><A HREF = "http://pympi.sourceforge.net/">pyMPI</A>
|
|
<LI><A HREF = "http://code.google.com/p/maroonmpi/">maroonmpi</A>
|
|
<LI><A HREF = "http://code.google.com/p/mpi4py/">mpi4py</A>
|
|
<LI><A HREF = "http://nbcr.sdsc.edu/forum/viewtopic.php?t=89&sid=c997fefc3933bd66204875b436940f16">myMPI</A>
|
|
<LI><A HREF = "http://code.google.com/p/pypar">Pypar</A>
|
|
</UL>
|
|
<P>All of these except pyMPI work by wrapping the MPI library and
|
|
exposing (some portion of) its interface to your Python script. This
|
|
means Python cannot be used interactively in parallel, since they do
|
|
not address the issue of interactive input to multiple instances of
|
|
Python running on different processors. The one exception is pyMPI,
|
|
which alters the Python interpreter to address this issue, and (I
|
|
believe) creates a new alternate executable (in place of "python"
|
|
itself) as a result.
|
|
</P>
|
|
<P>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.
|
|
</P>
|
|
<P>The one I recommend, since I have successfully used it with LAMMPS, is
|
|
Pypar. Pypar requires the ubiquitous <A HREF = "http://numpy.scipy.org">Numpy
|
|
package</A> be installed in your Python. After
|
|
launching python, type
|
|
</P>
|
|
<PRE>import numpy
|
|
</PRE>
|
|
<P>to see if it is installed. If not, here is how to install it (version
|
|
1.3.0b1 as of April 2009). Unpack the numpy tarball and from its
|
|
top-level directory, type
|
|
</P>
|
|
<PRE>python setup.py build
|
|
sudo python setup.py install
|
|
</PRE>
|
|
<P>The "sudo" is only needed if required to copy Numpy files into your
|
|
Python distribution's site-packages directory.
|
|
</P>
|
|
<P>To install Pypar (version pypar-2.1.4_94 as of Aug 2012), unpack it
|
|
and from its "source" directory, type
|
|
</P>
|
|
<PRE>python setup.py build
|
|
sudo python setup.py install
|
|
</PRE>
|
|
<P>Again, the "sudo" is only needed if required to copy Pypar files into
|
|
your Python distribution's site-packages directory.
|
|
</P>
|
|
<P>If you have successully installed Pypar, you should be able to run
|
|
Python and type
|
|
</P>
|
|
<PRE>import pypar
|
|
</PRE>
|
|
<P>without error. You should also be able to run python in parallel
|
|
on a simple test script
|
|
</P>
|
|
<PRE>% mpirun -np 4 python test.py
|
|
</PRE>
|
|
<P>where test.py contains the lines
|
|
</P>
|
|
<PRE>import pypar
|
|
print "Proc %d out of %d procs" % (pypar.rank(),pypar.size())
|
|
</PRE>
|
|
<P>and see one line of output for each processor you run on.
|
|
</P>
|
|
<P>IMPORTANT NOTE: To use Pypar and LAMMPS in parallel from Python, you
|
|
must insure both are using the same version of MPI. If you only have
|
|
one MPI installed on your system, this is not an issue, but it can be
|
|
if you have multiple MPIs. Your LAMMPS build is explicit about which
|
|
MPI it is using, since you specify the details in your lo-level
|
|
src/MAKE/Makefile.foo file. Pypar uses the "mpicc" command to find
|
|
information about the MPI it uses to build against. And it tries to
|
|
load "libmpi.so" from the LD_LIBRARY_PATH. This may or may not find
|
|
the MPI library that LAMMPS is using. If you have problems running
|
|
both Pypar and LAMMPS together, this is an issue you may need to
|
|
address, e.g. by moving other MPI installations so that Pypar finds
|
|
the right one.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_4"></A><H4>11.4 Testing the Python-LAMMPS interface
|
|
</H4>
|
|
<P>To test if LAMMPS is callable from Python, launch Python interactively
|
|
and type:
|
|
</P>
|
|
<PRE>>>> from lammps import lammps
|
|
>>> lmp = lammps()
|
|
</PRE>
|
|
<P>If you get no errors, you're ready to use LAMMPS from Python. If the
|
|
2nd command fails, the most common error to see is
|
|
</P>
|
|
<PRE>OSError: Could not load LAMMPS dynamic library
|
|
</PRE>
|
|
<P>which means Python was unable to load the LAMMPS shared library. This
|
|
typically occurs if the system can't find the LAMMPS shared library or
|
|
one of the auxiliary shared libraries it depends on, or if something
|
|
about the library is incompatible with your Python. The error message
|
|
should give you an indication of what went wrong.
|
|
</P>
|
|
<P>You can also test the load directly in Python as follows, without
|
|
first importing from the lammps.py file:
|
|
</P>
|
|
<PRE>>>> from ctypes import CDLL
|
|
>>> CDLL("liblammps.so")
|
|
</PRE>
|
|
<P>If an error occurs, carefully go thru the steps in <A HREF = "Section_start.html#start_5">Section_start
|
|
5</A> and above about building a shared
|
|
library and about insuring Python can find the necessary two files
|
|
it needs.
|
|
</P>
|
|
<H5><B>Test LAMMPS and Python in serial:</B>
|
|
</H5>
|
|
<P>To run a LAMMPS test in serial, type these lines into Python
|
|
interactively from the bench directory:
|
|
</P>
|
|
<PRE>>>> from lammps import lammps
|
|
>>> lmp = lammps()
|
|
>>> lmp.file("in.lj")
|
|
</PRE>
|
|
<P>Or put the same lines in the file test.py and run it as
|
|
</P>
|
|
<PRE>% python test.py
|
|
</PRE>
|
|
<P>Either way, you should see the results of running the in.lj benchmark
|
|
on a single processor appear on the screen, the same as if you had
|
|
typed something like:
|
|
</P>
|
|
<PRE>lmp_g++ < in.lj
|
|
</PRE>
|
|
<H5><B>Test LAMMPS and Python in parallel:</B>
|
|
</H5>
|
|
<P>To run LAMMPS in parallel, assuming you have installed the
|
|
<A HREF = "http://datamining.anu.edu.au/~ole/pypar">Pypar</A> package as discussed
|
|
above, create a test.py file containing these lines:
|
|
</P>
|
|
<PRE>import pypar
|
|
from lammps import lammps
|
|
lmp = lammps()
|
|
lmp.file("in.lj")
|
|
print "Proc %d out of %d procs has" % (pypar.rank(),pypar.size()),lmp
|
|
pypar.finalize()
|
|
</PRE>
|
|
<P>You can then run it in parallel as:
|
|
</P>
|
|
<PRE>% mpirun -np 4 python test.py
|
|
</PRE>
|
|
<P>and you should see the same output as if you had typed
|
|
</P>
|
|
<PRE>% mpirun -np 4 lmp_g++ < in.lj
|
|
</PRE>
|
|
<P>Note that if you leave out the 3 lines from test.py that specify Pypar
|
|
commands you will instantiate and run LAMMPS independently on each of
|
|
the P processors specified in the mpirun command. In this case you
|
|
should get 4 sets of output, each showing that a LAMMPS run was made
|
|
on a single processor, instead of one set of output showing that
|
|
LAMMPS ran on 4 processors. If the 1-processor outputs occur, it
|
|
means that Pypar is not working correctly.
|
|
</P>
|
|
<P>Also note that once you import the PyPar module, Pypar initializes MPI
|
|
for you, and you can use MPI calls directly in your Python script, as
|
|
described in the Pypar documentation. The last line of your Python
|
|
script should be pypar.finalize(), to insure MPI is shut down
|
|
correctly.
|
|
</P>
|
|
<H5><B>Running Python scripts:</B>
|
|
</H5>
|
|
<P>Note that any Python script (not just for LAMMPS) can be invoked in
|
|
one of several ways:
|
|
</P>
|
|
<PRE>% python foo.script
|
|
% python -i foo.script
|
|
% foo.script
|
|
</PRE>
|
|
<P>The last command requires that the first line of the script be
|
|
something like this:
|
|
</P>
|
|
<PRE>#!/usr/local/bin/python
|
|
#!/usr/local/bin/python -i
|
|
</PRE>
|
|
<P>where the path points to where you have Python installed, and that you
|
|
have made the script file executable:
|
|
</P>
|
|
<PRE>% chmod +x foo.script
|
|
</PRE>
|
|
<P>Without the "-i" flag, Python will exit when the script finishes.
|
|
With the "-i" flag, you will be left in the Python interpreter when
|
|
the script finishes, so you can type subsequent commands. As
|
|
mentioned above, you can only run Python interactively when running
|
|
Python on a single processor, not in parallel.
|
|
</P>
|
|
<HR>
|
|
|
|
<HR>
|
|
|
|
<A NAME = "py_5"></A><H4>11.5 Using LAMMPS from Python
|
|
</H4>
|
|
<P>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:
|
|
</P>
|
|
<PRE>from lammps import lammps
|
|
</PRE>
|
|
<P>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.
|
|
</P>
|
|
<PRE>lmp = lammps() # create a LAMMPS object using the default liblammps.so library
|
|
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>
|
|
<PRE>lmp.close() # destroy a LAMMPS object
|
|
</PRE>
|
|
<PRE>lmp.file(file) # run an entire input script, file = "in.lj"
|
|
lmp.command(cmd) # invoke a single LAMMPS command, cmd = "run 100"
|
|
</PRE>
|
|
<PRE>xlo = lmp.extract_global(name,type) # extract a global quantity
|
|
# name = "boxxlo", "nlocal", etc
|
|
# type = 0 = int
|
|
# 1 = double
|
|
</PRE>
|
|
<PRE>coords = lmp.extract_atom(name,type) # extract a per-atom quantity
|
|
# name = "x", "type", etc
|
|
# type = 0 = vector of ints
|
|
# 1 = array of ints
|
|
# 2 = vector of doubles
|
|
# 3 = array of doubles
|
|
</PRE>
|
|
<PRE>eng = lmp.extract_compute(id,style,type) # extract value(s) from a compute
|
|
v3 = lmp.extract_fix(id,style,type,i,j) # extract value(s) from a fix
|
|
# id = ID of compute or fix
|
|
# style = 0 = global data
|
|
# 1 = per-atom data
|
|
# 2 = local data
|
|
# type = 0 = scalar
|
|
# 1 = vector
|
|
# 2 = array
|
|
# i,j = indices of value in global vector or array
|
|
</PRE>
|
|
<PRE>var = lmp.extract_variable(name,group,flag) # extract value(s) from a variable
|
|
# name = name of variable
|
|
# group = group ID (ignored for equal-style variables)
|
|
# flag = 0 = equal-style variable
|
|
# 1 = atom-style variable
|
|
</PRE>
|
|
<PRE>natoms = lmp.get_natoms() # total # of atoms as int
|
|
data = lmp.gather_atoms(name,type,count) # return atom attribute of all atoms gathered into data, ordered by atom ID
|
|
# name = "x", "charge", "type", etc
|
|
# count = # of per-atom values, 1 or 3, etc
|
|
lmp.scatter_atoms(name,type,count,data) # scatter atom attribute of all atoms from data, ordered by atom ID
|
|
# name = "x", "charge", "type", etc
|
|
# count = # of per-atom values, 1 or 3, etc
|
|
</PRE>
|
|
<HR>
|
|
|
|
<P>IMPORTANT NOTE: Currently, the creation of a LAMMPS object from within
|
|
lammps.py does not take an MPI communicator as an argument. There
|
|
should be a way to do this, so that the LAMMPS instance runs on a
|
|
subset of processors if desired, but I don't know how to do it from
|
|
Pypar. So for now, it runs with MPI_COMM_WORLD, which is all the
|
|
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.
|
|
</P>
|
|
<P>Note that you can create multiple LAMMPS objects in your Python
|
|
script, and coordinate and run multiple simulations, e.g.
|
|
</P>
|
|
<PRE>from lammps import lammps
|
|
lmp1 = lammps()
|
|
lmp2 = lammps()
|
|
lmp1.file("in.file1")
|
|
lmp2.file("in.file2")
|
|
</PRE>
|
|
<P>The file() and command() methods allow an input script or single
|
|
commands to be invoked.
|
|
</P>
|
|
<P>The extract_global(), extract_atom(), extract_compute(),
|
|
extract_fix(), and extract_variable() methods return values or
|
|
pointers to data structures internal to LAMMPS.
|
|
</P>
|
|
<P>For extract_global() see the src/library.cpp file for the list of
|
|
valid names. New names could easily be added. A double or integer is
|
|
returned. You need to specify the appropriate data type via the type
|
|
argument.
|
|
</P>
|
|
<P>For extract_atom(), a pointer to internal LAMMPS atom-based data is
|
|
returned, which you can use via normal Python subscripting. See the
|
|
extract() method in the src/atom.cpp file for a list of valid names.
|
|
Again, new names could easily be added. A pointer to a vector of
|
|
doubles or integers, or a pointer to an array of doubles (double **)
|
|
or integers (int **) is returned. You need to specify the appropriate
|
|
data type via the type argument.
|
|
</P>
|
|
<P>For extract_compute() and extract_fix(), the global, per-atom, or
|
|
local data calulated by the compute or fix can be accessed. What is
|
|
returned depends on whether the compute or fix calculates a scalar or
|
|
vector or array. For a scalar, a single double value is returned. If
|
|
the compute or fix calculates a vector or array, a pointer to the
|
|
internal LAMMPS data is returned, which you can use via normal Python
|
|
subscripting. The one exception is that for a fix that calculates a
|
|
global vector or array, a single double value from the vector or array
|
|
is returned, indexed by I (vector) or I and J (array). I,J are
|
|
zero-based indices. The I,J arguments can be left out if not needed.
|
|
See <A HREF = "Section_howto.html#howto_15">Section_howto 15</A> of the manual for a
|
|
discussion of global, per-atom, and local data, and of scalar, vector,
|
|
and array data types. See the doc pages for individual
|
|
<A HREF = "compute.html">computes</A> and <A HREF = "fix.html">fixes</A> for a description of what
|
|
they calculate and store.
|
|
</P>
|
|
<P>For extract_variable(), an <A HREF = "variable.html">equal-style or atom-style
|
|
variable</A> is evaluated and its result returned.
|
|
</P>
|
|
<P>For equal-style variables a single double value is returned and the
|
|
group argument is ignored. For atom-style variables, a vector of
|
|
doubles is returned, one value per atom, which you can use via normal
|
|
Python subscripting. The values will be zero for atoms not in the
|
|
specified group.
|
|
</P>
|
|
<P>The get_natoms() method returns the total number of atoms in the
|
|
simulation, as an int.
|
|
</P>
|
|
<P>The gather_atoms() method returns a ctypes vector of ints or doubles
|
|
as specified by type, of length count*natoms, for the property of all
|
|
the atoms in the simulation specified by name, ordered by count and
|
|
then by atom ID. The vector can be used via normal Python
|
|
subscripting. If atom IDs are not consecutively ordered within
|
|
LAMMPS, a None is returned as indication of an error.
|
|
</P>
|
|
<P>Note that the data structure gather_atoms("x") returns is different
|
|
from the data structure returned by extract_atom("x") in four ways.
|
|
(1) Gather_atoms() returns a vector which you index as x[i];
|
|
extract_atom() returns an array which you index as x[i][j]. (2)
|
|
Gather_atoms() orders the atoms by atom ID while extract_atom() does
|
|
not. (3) Gathert_atoms() returns a list of all atoms in the
|
|
simulation; extract_atoms() returns just the atoms local to each
|
|
processor. (4) Finally, the gather_atoms() data structure is a copy
|
|
of the atom coords stored internally in LAMMPS, whereas extract_atom()
|
|
returns an array that effectively points directly to the internal
|
|
data. This means you can change values inside LAMMPS from Python by
|
|
assigning a new values to the extract_atom() array. To do this with
|
|
the gather_atoms() vector, you need to change values in the vector,
|
|
then invoke the scatter_atoms() method.
|
|
</P>
|
|
<P>The scatter_atoms() method takes a vector of ints or doubles as
|
|
specified by type, of length count*natoms, for the property of all the
|
|
atoms in the simulation specified by name, ordered by bount and then
|
|
by atom ID. It uses the vector of data to overwrite the corresponding
|
|
properties for each atom inside LAMMPS. This requires LAMMPS to have
|
|
its "map" option enabled; see the <A HREF = "atom_modify.html">atom_modify</A>
|
|
command for details. If it is not, or if atom IDs are not
|
|
consecutively ordered, no coordinates are reset.
|
|
</P>
|
|
<P>The array of coordinates passed to scatter_atoms() must be a ctypes
|
|
vector of ints or doubles, allocated and initialized something like
|
|
this:
|
|
</P>
|
|
<PRE>from ctypes import *
|
|
natoms = lmp.get_natoms()
|
|
n3 = 3*natoms
|
|
x = (n3*c_double)()
|
|
x<B>0</B> = x coord of atom with ID 1
|
|
x<B>1</B> = y coord of atom with ID 1
|
|
x<B>2</B> = z coord of atom with ID 1
|
|
x<B>3</B> = x coord of atom with ID 2
|
|
...
|
|
x<B>n3-1</B> = z coord of atom with ID natoms
|
|
lmp.scatter_coords("x",1,3,x)
|
|
</PRE>
|
|
<P>Alternatively, you can just change values in the vector returned by
|
|
gather_atoms("x",1,3), since it is a ctypes vector of doubles.
|
|
</P>
|
|
<HR>
|
|
|
|
<P>As noted above, these Python class methods correspond one-to-one with
|
|
the functions in the LAMMPS library interface in src/library.cpp and
|
|
library.h. This means you can extend the Python wrapper via the
|
|
following steps:
|
|
</P>
|
|
<UL><LI>Add a new interface function to src/library.cpp and
|
|
src/library.h.
|
|
|
|
<LI>Rebuild LAMMPS as a shared library.
|
|
|
|
<LI>Add a wrapper method to python/lammps.py for this interface
|
|
function.
|
|
|
|
<LI>You should now be able to invoke the new interface function from a
|
|
Python script. Isn't ctypes amazing?
|
|
</UL>
|
|
<HR>
|
|
|
|
<HR>
|
|
|
|
<A NAME = "py_6"></A><H4>11.6 Example Python scripts that use LAMMPS
|
|
</H4>
|
|
<P>These are the Python scripts included as demos in the python/examples
|
|
directory of the LAMMPS distribution, to illustrate the kinds of
|
|
things that are possible when Python wraps LAMMPS. If you create your
|
|
own scripts, send them to us and we can include them in the LAMMPS
|
|
distribution.
|
|
</P>
|
|
<DIV ALIGN=center><TABLE BORDER=1 >
|
|
<TR><TD >trivial.py</TD><TD > read/run a LAMMPS input script thru Python</TD></TR>
|
|
<TR><TD >demo.py</TD><TD > invoke various LAMMPS library interface routines</TD></TR>
|
|
<TR><TD >simple.py</TD><TD > mimic operation of couple/simple/simple.cpp in Python</TD></TR>
|
|
<TR><TD >gui.py</TD><TD > GUI go/stop/temperature-slider to control LAMMPS</TD></TR>
|
|
<TR><TD >plot.py</TD><TD > real-time temeperature plot with GnuPlot via Pizza.py</TD></TR>
|
|
<TR><TD >viz_tool.py</TD><TD > real-time viz via some viz package</TD></TR>
|
|
<TR><TD >vizplotgui_tool.py</TD><TD > combination of viz_tool.py and plot.py and gui.py
|
|
</TD></TR></TABLE></DIV>
|
|
|
|
<HR>
|
|
|
|
<P>For the viz_tool.py and vizplotgui_tool.py commands, replace "tool"
|
|
with "gl" or "atomeye" or "pymol" or "vmd", depending on what
|
|
visualization package you have installed.
|
|
</P>
|
|
<P>Note that for GL, you need to be able to run the Pizza.py GL tool,
|
|
which is included in the pizza sub-directory. See the <A HREF = "http://www.sandia.gov/~sjplimp/pizza.html">Pizza.py doc
|
|
pages</A> for more info:
|
|
</P>
|
|
|
|
|
|
<P>Note that for AtomEye, you need version 3, and there is a line in the
|
|
scripts that specifies the path and name of the executable. See the
|
|
AtomEye WWW pages <A HREF = "http://mt.seas.upenn.edu/Archive/Graphics/A">here</A> or <A HREF = "http://mt.seas.upenn.edu/Archive/Graphics/A3/A3.html">here</A> for more details:
|
|
</P>
|
|
<PRE>http://mt.seas.upenn.edu/Archive/Graphics/A
|
|
http://mt.seas.upenn.edu/Archive/Graphics/A3/A3.html
|
|
</PRE>
|
|
|
|
|
|
|
|
|
|
<P>The latter link is to AtomEye 3 which has the scriping
|
|
capability needed by these Python scripts.
|
|
</P>
|
|
<P>Note that for PyMol, you need to have built and installed the
|
|
open-source version of PyMol in your Python, so that you can import it
|
|
from a Python script. See the PyMol WWW pages <A HREF = "http://www.pymol.org">here</A> or
|
|
<A HREF = "http://sourceforge.net/scm/?type=svn&group_id=4546">here</A> for more details:
|
|
</P>
|
|
<PRE>http://www.pymol.org
|
|
http://sourceforge.net/scm/?type=svn&group_id=4546
|
|
</PRE>
|
|
|
|
|
|
|
|
|
|
<P>The latter link is to the open-source version.
|
|
</P>
|
|
<P>Note that for VMD, you need a fairly current version (1.8.7 works for
|
|
me) and there are some lines in the pizza/vmd.py script for 4 PIZZA
|
|
variables that have to match the VMD installation on your system.
|
|
</P>
|
|
<HR>
|
|
|
|
<P>See the python/README file for instructions on how to run them and the
|
|
source code for individual scripts for comments about what they do.
|
|
</P>
|
|
<P>Here are screenshots of the vizplotgui_tool.py script in action for
|
|
different visualization package options. Click to see larger images:
|
|
</P>
|
|
<A HREF = "JPG/screenshot_gl.jpg"><IMG SRC = "JPG/screenshot_gl_small.jpg"></A>
|
|
|
|
<A HREF = "JPG/screenshot_atomeye.jpg"><IMG SRC = "JPG/screenshot_atomeye_small.jpg"></A>
|
|
|
|
<A HREF = "JPG/screenshot_pymol.jpg"><IMG SRC = "JPG/screenshot_pymol_small.jpg"></A>
|
|
|
|
<A HREF = "JPG/screenshot_vmd.jpg"><IMG SRC = "JPG/screenshot_vmd_small.jpg"></A>
|
|
|
|
</HTML>
|