forked from lijiext/lammps
677 lines
29 KiB
HTML
677 lines
29 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>The LAMMPS distribution includes some Python code in its python
|
|
directory which wraps the library interface to LAMMPS. This 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.
|
|
</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">this
|
|
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_4">this section</A> about how
|
|
to build LAMMPS as a library, and <A HREF = "Section_howto.html#howto_19">this
|
|
section</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 has the effect of extending the Python inteface as well. See
|
|
details below.
|
|
</P>
|
|
<P>By using the Python interface LAMMPS can also be coupled with a GUI or
|
|
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, the Python on your machine
|
|
must be "extended" to include an interface to the LAMMPS library. If
|
|
your Python script will invoke MPI operations, you will also need to
|
|
extend your Python with an interface to MPI itself.
|
|
</P>
|
|
<P>Thus you should first decide how you intend to use LAMMPS from Python.
|
|
There are 3 options:
|
|
</P>
|
|
<P>(1) Use LAMMPS on a single processor running Python.
|
|
</P>
|
|
<P>(2) Use LAMMPS in parallel, where each processor runs Python, but your
|
|
Python program does not use MPI.
|
|
</P>
|
|
<P>(3) Use LAMMPS in parallel, where each processor runs Python, and your
|
|
Python script also makes MPI calls through a Python/MPI interface.
|
|
</P>
|
|
<P>Note that for (2) and (3) you will not be able to use Python
|
|
interactively by typing commands and getting a response. This is
|
|
because you will have multiple instances of Python running (e.g. on a
|
|
parallel machine) and they cannot all read what you type.
|
|
</P>
|
|
<P>Working in mode (1) does not require your machine to have MPI
|
|
installed. You should extend your Python with a serial version of
|
|
LAMMPS and the dummy MPI library provided with LAMMPS. See
|
|
instructions below on how to do this.
|
|
</P>
|
|
<P>Working in mode (2) requires your machine to have an MPI library
|
|
installed, but your Python does not need to be extended with MPI
|
|
itself. The MPI library must be a shared library (e.g. a *.so file on
|
|
Linux) which is not typically created when MPI is built/installed.
|
|
See instruction below on how to do this. You should extend your
|
|
Python with the a parallel versionn of LAMMPS which will use the
|
|
shared MPI system library. See instructions below on how to do this.
|
|
</P>
|
|
<P>Working in mode (3) requires your machine to have MPI installed (as a
|
|
shared library as in (2)). You must also extend your Python with a
|
|
parallel version of LAMMPS (same as in (2)) and with MPI itself, via
|
|
one of several available Python/MPI packages. See instructions below
|
|
on how to do the latter task.
|
|
</P>
|
|
<P>Several of the following sub-sections cover the rest of the Python
|
|
setup discussion. The next to last sub-section describes the Python
|
|
syntax used to invoke LAMMPS. The last sub-section describes example
|
|
Python scripts included in the python directory.
|
|
</P>
|
|
<UL><LI>11.1 <A HREF = "#py_1">Extending Python with a serial version of LAMMPS</A>
|
|
<LI>11.2 <A HREF = "#py_2">Creating a shared MPI library</A>
|
|
<LI>11.3 <A HREF = "#py_3">Extending Python with a parallel version of LAMMPS</A>
|
|
<LI>11.4 <A HREF = "#py_4">Extending Python with MPI</A>
|
|
<LI>11.5 <A HREF = "#py_5">Testing the Python-LAMMPS interface</A>
|
|
<LI>11.6 <A HREF = "#py_6">Using LAMMPS from Python</A>
|
|
<LI>11.7 <A HREF = "#py_7">Example Python scripts that use LAMMPS</A>
|
|
</UL>
|
|
<P>Before proceeding, there are 2 items to note.
|
|
</P>
|
|
<P>(1) The provided 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>
|
|
<P>(2) Any library wrapped by Python, including LAMMPS, must be built as
|
|
a shared library (e.g. a *.so file on Linux and not a *.a file). The
|
|
python/setup_serial.py and setup.py scripts do this build for LAMMPS
|
|
itself (described below). But if you have LAMMPS configured to use
|
|
additional packages that have their own libraries, then those
|
|
libraries must also be shared libraries. E.g. MPI, FFTW, or any of
|
|
the libraries in lammps/lib. When you build LAMMPS as a stand-alone
|
|
code, you are not building shared versions of these libraries.
|
|
</P>
|
|
<P>The discussion below describes how to create a shared MPI library. I
|
|
suggest you start by configuing LAMMPS without packages installed that
|
|
require any libraries besides MPI. See <A HREF = "Section_start.html#start_3">this
|
|
section</A> of the manual for a discussion of
|
|
LAMMPS pacakges. E.g. do not use the KSPACE, GPU, MEAM, POEMS, or
|
|
REAX packages.
|
|
</P>
|
|
<P>If you are successfully follow the steps belwo to build the Python
|
|
wrappers and use this version of LAMMPS through Python, you can then
|
|
take the next step of adding LAMMPS packages that use additional
|
|
libraries. This will require you to build a shared library for that
|
|
package's library, similar to what is described below for MPI. It
|
|
will also require you to edit the python/setup_serial.py or setup.py
|
|
scripts to enable Python to access those libraries when it builds the
|
|
LAMMPS wrapper.
|
|
</P>
|
|
<HR>
|
|
|
|
<HR>
|
|
|
|
<A NAME = "py_1"></A><H4>11.1 Extending Python with a serial version of LAMMPS
|
|
</H4>
|
|
<P>From the python directory in the LAMMPS distribution, type
|
|
</P>
|
|
<PRE>python setup_serial.py build
|
|
</PRE>
|
|
<P>and then one of these commands:
|
|
</P>
|
|
<PRE>sudo python setup_serial.py install
|
|
python setup_serial.py install --home=~/foo
|
|
</PRE>
|
|
<P>The "build" command should compile all the needed LAMMPS files,
|
|
including its dummy MPI library. The first "install" command will put
|
|
the needed files in your Python's site-packages sub-directory, so that
|
|
Python can load them. For example, if you installed Python yourself
|
|
on a Linux machine, it would typically be somewhere like
|
|
/usr/local/lib/python2.5/site-packages. Installing Python packages
|
|
this way often requires you to be able to write to the Python
|
|
directories, which may require root priveleges, hence the "sudo"
|
|
prefix. If this is not the case, you can drop the "sudo".
|
|
</P>
|
|
<P>Alternatively, you can install the LAMMPS files (or any other Python
|
|
packages) in your own user space. The second "install" command does
|
|
this, where you should replace "foo" with your directory of choice.
|
|
</P>
|
|
<P>If these commands are successful, a <I>lammps.py</I> and
|
|
<I>_lammps_serial.so</I> file will be put in the appropriate directory.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_2"></A><H4>11.2 Creating a shared MPI library
|
|
</H4>
|
|
<P>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". Such a shared library is normally not built if you
|
|
installed MPI yourself, but it is easy to do. Here is how to do it
|
|
for <A HREF = "http://www-unix.mcs.anl.gov/mpi">MPICH</A>, a popular open-source version of MPI, distributed
|
|
by Argonne National Labs. From within the mpich directory, type
|
|
</P>
|
|
|
|
|
|
<PRE>./configure --enable-shared
|
|
make
|
|
make install
|
|
</PRE>
|
|
<P>You may need to use "sudo make install" in place of the last line.
|
|
The end result should be the file libmpich.so in /usr/local/lib.
|
|
</P>
|
|
<P>IMPORTANT NOTE: If the file libmpich.a already exists in your
|
|
installation directory (e.g. /usr/local/lib), you will now have both a
|
|
static and shared MPI library. This will be fine for running LAMMPS
|
|
from Python since it only uses the shared library. But if you now try
|
|
to build LAMMPS by itself as a stand-alone program (cd lammps/src;
|
|
make foo) or build other codes that expect to link against libmpich.a,
|
|
then those builds may fail if the linker uses libmpich.so instead. If
|
|
this happens, it means you will need to remove the file
|
|
/usr/local/lib/libmich.so before building LAMMPS again as a
|
|
stand-alone code.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_3"></A><H4>11.3 Extending Python with a parallel version of LAMMPS
|
|
</H4>
|
|
<P>From the python directory, type
|
|
</P>
|
|
<PRE>python setup.py build
|
|
</PRE>
|
|
<P>and then one of these commands:
|
|
</P>
|
|
<PRE>sudo python setup.py install
|
|
python setup.py install --home=~/foo
|
|
</PRE>
|
|
<P>The "build" command should compile all the needed LAMMPS C++ files,
|
|
which will require MPI to be installed on your system. This means it
|
|
must find both the header file mpi.h and a shared library file,
|
|
e.g. libmpich.so if the MPICH version of MPI is installed. See the
|
|
preceding section for how to create a shared library version of MPI if
|
|
it does not exist. You may need to adjust the "include_dirs" and
|
|
"library_dirs" and "libraries" fields in python/setup.py to
|
|
insure the Python build finds all the files it needs.
|
|
</P>
|
|
<P>The first "install" command will put the needed files in your Python's
|
|
site-packages sub-directory, so that Python can load them. For
|
|
example, if you installed Python yourself on a Linux machine, it would
|
|
typically be somewhere like /usr/local/lib/python2.5/site-packages.
|
|
Installing Python packages this way often requires you to be able to
|
|
write to the Python directories, which may require root priveleges,
|
|
hence the "sudo" prefix. If this is not the case, you can drop the
|
|
"sudo".
|
|
</P>
|
|
<P>Alternatively, you can install the LAMMPS files (or any other Python
|
|
packages) in your own user space. The second "install" command does
|
|
this, where you should replace "foo" with your directory of choice.
|
|
</P>
|
|
<P>If these commands are successful, a <I>lammps.py</I> and <I>_lammps.so</I> file
|
|
will be put in the appropriate directory.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_4"></A><H4>11.4 Extending Python with MPI
|
|
</H4>
|
|
<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://datamining.anu.edu.au/~ole/pypar">Pypar</A>
|
|
</UL>
|
|
<P>All of these except pyMPI work by wrapping the MPI library (which must
|
|
be available on your system as a shared library, as discussed above),
|
|
and exposing (some portion of) its interface to your Python script.
|
|
This means they 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
|
|
both calls to LAMMPS and MPI itself from a Python script running in
|
|
parallel. However, when I downloaded and looked at a few of them,
|
|
their docuemtation 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.0_66 as of April 2009), 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 serially 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.script
|
|
</PRE>
|
|
<P>where test.script 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 ran on.
|
|
</P>
|
|
<HR>
|
|
|
|
<A NAME = "py_5"></A><H4>11.5 Testing the Python-LAMMPS interface
|
|
</H4>
|
|
<P>Before using LAMMPS in a Python program, one more step is needed. The
|
|
interface to LAMMPS is via the Python ctypes package, which loads the
|
|
shared LAMMPS library via a CDLL() call, which in turn is a wrapper on
|
|
the C-library dlopen(). This command is different than a normal
|
|
Python "import" and needs to be able to find the LAMMPS shared
|
|
library, which is either in the Python site-packages directory or in a
|
|
local directory you specified in the "python setup.py install"
|
|
command, as described above.
|
|
</P>
|
|
<P>The simplest way to do this is add a line like this to your
|
|
.cshrc or other shell start-up file.
|
|
</P>
|
|
<PRE>setenv LD_LIBRARY_PATH
|
|
${LD_LIBRARY_PATH}:/usr/local/lib/python2.5/site-packages
|
|
</PRE>
|
|
<P>and then execute the shell file to insure the path has been updated.
|
|
This will extend the path that dlopen() uses to look for shared
|
|
libraries.
|
|
</P>
|
|
<P>To test if the serial LAMMPS library has been successfully installed
|
|
(mode 1 above), launch Python and type
|
|
</P>
|
|
<PRE>>>> from lammps import lammps
|
|
>>> lmp = lammps()
|
|
</PRE>
|
|
<P>If you get no errors, you're ready to use serial LAMMPS from Python.
|
|
</P>
|
|
<P>If you built LAMMPS for parallel use (mode 2 or 3 above), launch
|
|
Python in parallel:
|
|
</P>
|
|
<PRE>% mpirun -np 4 python test.script
|
|
</PRE>
|
|
<P>where test.script contains the lines
|
|
</P>
|
|
<PRE>import pypar
|
|
from lammps import lammps
|
|
lmp = lammps()
|
|
print "Proc %d out of %d procs has" % (pypar.rank(),pypar.size()), lmp
|
|
pypar.finalize()
|
|
</PRE>
|
|
<P>Again, if you get no errors, you're good to go.
|
|
</P>
|
|
<P>Note that if you left out the "import pypar" line from this script,
|
|
you would instantiate and run LAMMPS independently on each of the P
|
|
processors specified in the mpirun command. You can test if Pypar is
|
|
enabling true parallel Python and LAMMPS by adding a line to the above
|
|
sequence of commands like lmp.file("in.lj") to run an input script and
|
|
see if the LAMMPS run says it ran on P processors or if you get output
|
|
from P duplicated 1-processor runs written to the screen. In the
|
|
latter case, Pypar is not working correctly.
|
|
</P>
|
|
<P>Note that this line:
|
|
</P>
|
|
<PRE>from lammps import lammps
|
|
</PRE>
|
|
<P>will import either the serial or parallel version of the LAMMPS
|
|
library, as wrapped by lammps.py. But if you installed both via
|
|
setup_serial.py and setup.py, it will always import the parallel
|
|
version, since it attempts that first.
|
|
</P>
|
|
<P>Note that if your Python script imports the Pypar package (as above),
|
|
so that it can use MPI calls directly, then Pypar initializes MPI for
|
|
you. Thus the last line of your Python script should be
|
|
pypar.finalize(), to insure MPI is shut down correctly.
|
|
</P>
|
|
<P>Also note that a Python script can be invoked in one of several ways:
|
|
</P>
|
|
<P>% python foo.script
|
|
% python -i foo.script
|
|
% foo.script
|
|
</P>
|
|
<P>The last command requires that the first line of the script be
|
|
something like this:
|
|
</P>
|
|
<P>#!/usr/local/bin/python
|
|
#!/usr/local/bin/python -i
|
|
</P>
|
|
<P>where the path points to where you have Python installed, and that you
|
|
have made the script file executable:
|
|
</P>
|
|
<P>% chmod +x foo.script
|
|
</P>
|
|
<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_6"></A><H4>11.6 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 and its settings as
|
|
follows:
|
|
</P>
|
|
<PRE>from lammps import lammps
|
|
from lammps import LMPINT as INT
|
|
from lammps import LMPDOUBLE as DOUBLE
|
|
from lammps import LMPIPTR as IPTR
|
|
from lammps import LMPDPTR as DPTR
|
|
from lammps import LMPDPTRPTR as DPTRPTR
|
|
</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
|
|
lmp = lammps(list) # ditto, with command-line args, list = ["-echo","screen"]
|
|
</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 = INT or DOUBLE
|
|
</PRE>
|
|
<PRE>coords = lmp.extract_atom(name,type) # extract a per-atom quantity
|
|
# name = "x", "type", etc
|
|
# type = IPTR or DPTR or DPTRPTR
|
|
</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
|
|
x = lmp.get_coords() # return coords of all atoms in x
|
|
lmp.put_coords(x) # set all atom coords via x
|
|
</PRE>
|
|
<HR>
|
|
|
|
<P>The creation of a LAMMPS object 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 yet
|
|
know how from Pypar. So for now, it runs on MPI_COMM_WORLD, which is
|
|
all the processors.
|
|
</P>
|
|
<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 **)
|
|
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">this section</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. Note that extract_global("natoms") returns the
|
|
same value, but as a double, which is the way LAMMPS stores it to
|
|
allow for systems with more atoms than can be stored in an int (> 2
|
|
billion).
|
|
</P>
|
|
<P>The get_coords() method returns an ctypes vector of doubles of length
|
|
3*natoms, for the coordinates of all the atoms in the simulation,
|
|
ordered by x,y,z and then by atom ID (see code for put_coords()
|
|
below). The array 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 get_coords() returns is different from
|
|
the data structure returned by extract_atom("x") in four ways. (1)
|
|
Get_coords() returns a vector which you index as x[i];
|
|
extract_atom() returns an array which you index as x[i][j]. (2)
|
|
Get_coords() orders the atoms by atom ID while extract_atom() does
|
|
not. (3) Get_coords() returns a list of all atoms in the simulation;
|
|
extract_atoms() returns just the atoms local to each processor. (4)
|
|
Finally, the get_coords() data structure is a copy of the atom coords
|
|
stored internally in LAMMPS, whereas extract_atom returns an array
|
|
that 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 get_atoms() vector, you
|
|
need to change values in the vector, then invoke the put_coords()
|
|
method.
|
|
</P>
|
|
<P>The put_coords() method takes a vector of coordinates for all atoms in
|
|
the simulation, assumed to be ordered by x,y,z and then by atom ID,
|
|
and uses the values to overwrite the corresponding coordinates 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 put_coords() must be a ctypes
|
|
vector of doubles, allocated and initialized something like this:
|
|
</P>
|
|
<PRE>from ctypes import *
|
|
natoms = lmp.get_atoms()
|
|
n3 = 3*natoms
|
|
x = (c_double*n3)()
|
|
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.put_coords(x)
|
|
</PRE>
|
|
<P>Alternatively, you can just change values in the vector returned by
|
|
get_coords(), 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>Verify the new function is syntactically correct by building LAMMPS as
|
|
a library - see <A HREF = "Section_start.html#start_4">this section</A> of the
|
|
manual.
|
|
|
|
<LI>Add a wrapper method in the Python LAMMPS module to python/lammps.py
|
|
for this interface function.
|
|
|
|
<LI>Rebuild the Python wrapper via python/setup_serial.py or
|
|
python/setup.py.
|
|
|
|
<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_7"></A><H4>11.7 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>
|