File: Section_python.html

package info (click to toggle)
lammps 0~20120615.gite442279-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 128,448 kB
  • sloc: cpp: 321,874; fortran: 15,187; ansic: 11,007; python: 7,889; perl: 2,915; sh: 2,088; makefile: 924; f90: 374; objc: 238; lisp: 169; csh: 16; tcl: 6
file content (686 lines) | stat: -rw-r--r-- 29,975 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
<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">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>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_5">Section_start 4</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>
<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 packages.  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".  If you use
the "sudo" prefix and you have installed Python yourself, you should
make sure that root uses the same Python as the one you did the
"install" in.  E.g. these 2 commands may do the install in different
Python versions:
</P>
<PRE>python setup_serial.py install --home=~/foo
python /usr/local/bin/python/setup_serial.py install --home=~/foo 
</PRE>
<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">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.  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_5">Section_start 4</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>