diff --git a/doc/src/Howto_pylammps.rst b/doc/src/Howto_pylammps.rst index 98c14c547d..64f1cc6036 100644 --- a/doc/src/Howto_pylammps.rst +++ b/doc/src/Howto_pylammps.rst @@ -57,7 +57,7 @@ output support enabled. Step 1a: For the CMake based build system, the steps are: -.. parsed-literal:: +.. code-block:: bash mkdir $LAMMPS_DIR/build-shared cd $LAMMPS_DIR/build-shared @@ -69,7 +69,7 @@ Step 1a: For the CMake based build system, the steps are: Step 1b: For the legacy, make based build system, the steps are: -.. parsed-literal:: +.. code-block:: bash cd $LAMMPS_DIR/src @@ -86,7 +86,7 @@ PyLammps is part of the lammps Python package. To install it simply install that package into your current Python installation with: -.. parsed-literal:: +.. code-block:: bash make install-python @@ -111,7 +111,7 @@ Benefits of using a virtualenv **Prerequisite (e.g. on Ubuntu)** -.. parsed-literal:: +.. code-block:: bash apt-get install python-virtualenv @@ -119,7 +119,7 @@ Creating a virtualenv with lammps installed """"""""""""""""""""""""""""""""""""""""""" -.. parsed-literal:: +.. code-block:: bash # create virtualenv named 'testing' virtualenv $HOME/python/testing @@ -133,7 +133,7 @@ need to re-run CMake to update the location of the python executable to the location in the virtual environment with: -.. parsed-literal:: +.. code-block:: bash cmake . -DPYTHON_EXECUTABLE=$(which python) @@ -155,7 +155,7 @@ To create a PyLammps object you need to first import the class from the lammps module. By using the default constructor, a new *lammps* instance is created. -.. parsed-literal:: +.. code-block:: Python from lammps import PyLammps L = PyLammps() @@ -163,7 +163,7 @@ module. By using the default constructor, a new *lammps* instance is created. You can also initialize PyLammps on top of this existing *lammps* object: -.. parsed-literal:: +.. code-block:: Python from lammps import lammps, PyLammps lmp = lammps() @@ -178,7 +178,7 @@ the command method of the lammps object instance. For instance, let's take the following LAMMPS command: -.. parsed-literal:: +.. code-block:: LAMMPS region box block 0 10 0 5 -0.5 0.5 @@ -186,7 +186,7 @@ In the original interface this command can be executed with the following Python code if *L* was a lammps instance: -.. parsed-literal:: +.. code-block:: Python L.command("region box block 0 10 0 5 -0.5 0.5") @@ -194,7 +194,7 @@ With the PyLammps interface, any command can be split up into arbitrary parts separated by white-space, passed as individual arguments to a region method. -.. parsed-literal:: +.. code-block:: Python L.region("box block", 0, 10, 0, 5, -0.5, 0.5) @@ -207,7 +207,7 @@ parameterization. In the original interface parameterization needed to be done manually by creating formatted strings. -.. parsed-literal:: +.. code-block:: Python L.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi)) @@ -215,7 +215,7 @@ In contrast, methods of PyLammps accept parameters directly and will convert them automatically to a final command string. -.. parsed-literal:: +.. code-block:: Python L.region("box block", xlo, xhi, ylo, yhi, zlo, zhi) @@ -270,7 +270,7 @@ LAMMPS variables can be both defined and accessed via the PyLammps interface. To define a variable you can use the :doc:`variable ` command: -.. parsed-literal:: +.. code-block:: Python L.variable("a index 2") @@ -280,7 +280,7 @@ you can access an individual variable by retrieving a variable object from the L.variables dictionary by name -.. parsed-literal:: +.. code-block:: Python a = L.variables['a'] @@ -288,7 +288,7 @@ The variable value can then be easily read and written by accessing the value property of this object. -.. parsed-literal:: +.. code-block:: Python print(a.value) a.value = 4 @@ -301,7 +301,7 @@ passed string parameter can be any expression containing global thermo values, variables, compute or fix data. -.. parsed-literal:: +.. code-block:: Python result = L.eval("ke") # kinetic energy result = L.eval("pe") # potential energy @@ -316,7 +316,7 @@ Each element of this list is an object which exposes its properties (id, type, position, velocity, force, etc.). -.. parsed-literal:: +.. code-block:: Python # access first atom L.atoms[0].id @@ -330,7 +330,7 @@ position, velocity, force, etc.). Some properties can also be used to set: -.. parsed-literal:: +.. code-block:: Python # set position in 2D simulation L.atoms[0].position = (1.0, 0.0) @@ -348,7 +348,7 @@ The first element is the output of the first run, the second element that of the second run. -.. parsed-literal:: +.. code-block:: Python L.run(1000) L.runs[0] # data of first 1000 time steps @@ -360,7 +360,7 @@ Each run contains a dictionary of all trajectories. Each trajectory is accessible through its thermo name: -.. parsed-literal:: +.. code-block:: Python L.runs[0].step # list of time steps in first run L.runs[0].ke # list of kinetic energy values in first run @@ -370,7 +370,7 @@ Together with matplotlib plotting data out of LAMMPS becomes simple: import matplotlib.plot as plt -.. parsed-literal:: +.. code-block:: Python steps = L.runs[0].step ke = L.runs[0].ke @@ -408,7 +408,7 @@ To launch an instance of Jupyter simply run the following command inside your Python environment (this assumes you followed the Quick Start instructions): -.. parsed-literal:: +.. code-block:: bash jupyter notebook @@ -431,7 +431,7 @@ them using a datafile. Then one of the atoms is rotated along the central axis b setting its position from Python, which changes the dihedral angle. -.. parsed-literal:: +.. code-block:: Python phi = [d \* math.pi / 180 for d in range(360)] @@ -465,7 +465,7 @@ Initially, a 2D system is created in a state with minimal energy. It is then disordered by moving each atom by a random delta. -.. parsed-literal:: +.. code-block:: Python random.seed(27848) deltaperturb = 0.2 @@ -485,7 +485,7 @@ Finally, the Monte Carlo algorithm is implemented in Python. It continuously moves random atoms by a random delta and only accepts certain moves. -.. parsed-literal:: +.. code-block:: Python estart = L.eval("pe") elast = estart @@ -538,7 +538,7 @@ Using PyLammps and mpi4py (Experimental) PyLammps can be run in parallel using mpi4py. This python package can be installed using -.. parsed-literal:: +.. code-block:: bash pip install mpi4py @@ -546,7 +546,7 @@ The following is a short example which reads in an existing LAMMPS input file an executes it in parallel. You can find in.melt in the examples/melt folder. -.. parsed-literal:: +.. code-block:: Python from mpi4py import MPI from lammps import PyLammps @@ -563,7 +563,7 @@ To run this script (melt.py) in parallel using 4 MPI processes we invoke the following mpirun command: -.. parsed-literal:: +.. code-block:: bash mpirun -np 4 python melt.py diff --git a/doc/txt/Howto_pylammps.txt b/doc/txt/Howto_pylammps.txt deleted file mode 100644 index 54f17d912a..0000000000 --- a/doc/txt/Howto_pylammps.txt +++ /dev/null @@ -1,481 +0,0 @@ -"LAMMPS WWW Site"_lws - "LAMMPS Documentation"_ld - "LAMMPS Commands"_lc :c - -:link(lws,http://lammps.sandia.gov) -:link(ld,Manual.html) -:link(lc,Commands_all.html) - -:line - -PyLammps Tutorial :h3 - - - -Overview :h4 - -PyLammps is a Python wrapper class which can be created on its own or -use an existing lammps Python object. It creates a simpler, -Python-like interface to common LAMMPS functionality, in contrast to -the lammps.py wrapper on the C-style LAMMPS library interface which is -written using Python ctypes. The lammps.py wrapper is discussed on -the "Python library"_Python_library.html doc page. - -Unlike the flat ctypes interface, PyLammps exposes a discoverable API. -It no longer requires knowledge of the underlying C++ code -implementation. Finally, the IPyLammps wrapper builds on top of -PyLammps and adds some additional features for IPython integration -into IPython notebooks, e.g. for embedded visualization output from -dump/image. - -Comparison of lammps and PyLammps interfaces :h5 - -lammps.lammps :h6 - -uses C-Types -direct memory access to native C++ data -provides functions to send and receive data to LAMMPS -requires knowledge of how LAMMPS internally works (C pointers, etc) :ul - -lammps.PyLammps :h6 - -higher-level abstraction built on top of original C-Types interface -manipulation of Python objects -communication with LAMMPS is hidden from API user -shorter, more concise Python -better IPython integration, designed for quick prototyping :ul - -Quick Start :h4 - -System-wide Installation :h5 - -Step 1: Building LAMMPS as a shared library :h6 - -To use LAMMPS inside of Python it has to be compiled as shared library. This -library is then loaded by the Python interface. In this example we enable the -MOLECULE package and compile LAMMPS with C++ exceptions, PNG, JPEG and FFMPEG -output support enabled. - -Step 1a: For the CMake based build system, the steps are: - -mkdir $LAMMPS_DIR/build-shared -cd $LAMMPS_DIR/build-shared :pre - -# MPI, PNG, Jpeg, FFMPEG are auto-detected -cmake ../cmake -DPKG_MOLECULE=yes -DLAMMPS_EXCEPTIONS=yes -DBUILD_LIB=yes -DBUILD_SHARED_LIBS=yes -make :pre - -Step 1b: For the legacy, make based build system, the steps are: - -cd $LAMMPS_DIR/src :pre - -# add packages if necessary -make yes-MOLECULE :pre - -# compile shared library using Makefile -make mpi mode=shlib LMP_INC="-DLAMMPS_PNG -DLAMMPS_JPEG -DLAMMPS_FFMPEG -DLAMMPS_EXCEPTIONS" JPG_LIB="-lpng -ljpeg" :pre - -Step 2: Installing the LAMMPS Python package :h6 - -PyLammps is part of the lammps Python package. To install it simply install -that package into your current Python installation with: - -make install-python :pre - -NOTE: Recompiling the shared library requires re-installing the Python package - - -Installation inside of a virtualenv :h5 - -You can use virtualenv to create a custom Python environment specifically tuned -for your workflow. - -Benefits of using a virtualenv :h6 - -isolation of your system Python installation from your development installation -installation can happen in your user directory without root access (useful for HPC clusters) -installing packages through pip allows you to get newer versions of packages than e.g., through apt-get or yum package managers (and without root access) -you can even install specific old versions of a package if necessary :ul - -[Prerequisite (e.g. on Ubuntu)] - -apt-get install python-virtualenv :pre - -Creating a virtualenv with lammps installed :h6 - -# create virtualenv named 'testing' -virtualenv $HOME/python/testing :pre - -# activate 'testing' environment -source $HOME/python/testing/bin/activate :pre - -Now configure and compile the LAMMPS shared library as outlined above. -When using CMake and the shared library has already been build, you -need to re-run CMake to update the location of the python executable -to the location in the virtual environment with: - -cmake . -DPYTHON_EXECUTABLE=$(which python) :pre - -# install LAMMPS package in virtualenv -(testing) make install-python :pre - -# install other useful packages -(testing) pip install matplotlib jupyter mpi4py :pre - -... :pre - -# return to original shell -(testing) deactivate :pre - - -Creating a new instance of PyLammps :h4 - -To create a PyLammps object you need to first import the class from the lammps -module. By using the default constructor, a new {lammps} instance is created. - -from lammps import PyLammps -L = PyLammps() :pre - -You can also initialize PyLammps on top of this existing {lammps} object: - -from lammps import lammps, PyLammps -lmp = lammps() -L = PyLammps(ptr=lmp) :pre - -Commands :h4 - -Sending a LAMMPS command with the existing library interfaces is done using -the command method of the lammps object instance. - -For instance, let's take the following LAMMPS command: - -region box block 0 10 0 5 -0.5 0.5 :pre - -In the original interface this command can be executed with the following -Python code if {L} was a lammps instance: - -L.command("region box block 0 10 0 5 -0.5 0.5") :pre - -With the PyLammps interface, any command can be split up into arbitrary parts -separated by white-space, passed as individual arguments to a region method. - -L.region("box block", 0, 10, 0, 5, -0.5, 0.5) :pre - -Note that each parameter is set as Python literal floating-point number. In the -PyLammps interface, each command takes an arbitrary parameter list and transparently -merges it to a single command string, separating individual parameters by white-space. - -The benefit of this approach is avoiding redundant command calls and easier -parameterization. In the original interface parameterization needed to be done -manually by creating formatted strings. - -L.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi)) :pre - -In contrast, methods of PyLammps accept parameters directly and will convert -them automatically to a final command string. - -L.region("box block", xlo, xhi, ylo, yhi, zlo, zhi) :pre - -System state :h4 - -In addition to dispatching commands directly through the PyLammps object, it -also provides several properties which allow you to query the system state. - -:dlb - -L.system :dt - -Is a dictionary describing the system such as the bounding box or number of atoms :dd - -L.system.xlo, L.system.xhi :dt - -bounding box limits along x-axis :dd - -L.system.ylo, L.system.yhi :dt - -bounding box limits along y-axis :dd - -L.system.zlo, L.system.zhi :dt - -bounding box limits along z-axis :dd - -L.communication :dt - -configuration of communication subsystem, such as the number of threads or processors :dd - -L.communication.nthreads :dt - -number of threads used by each LAMMPS process :dd - -L.communication.nprocs :dt - -number of MPI processes used by LAMMPS :dd - -L.fixes :dt - -List of fixes in the current system :dd - -L.computes :dt - -List of active computes in the current system :dd - -L.dump :dt - -List of active dumps in the current system :dd - -L.groups :dt - -List of groups present in the current system :dd - -:dle - -Working with LAMMPS variables :h4 - -LAMMPS variables can be both defined and accessed via the PyLammps interface. - -To define a variable you can use the "variable"_variable.html command: - -L.variable("a index 2") :pre - -A dictionary of all variables is returned by L.variables - -you can access an individual variable by retrieving a variable object from the -L.variables dictionary by name - -a = L.variables\['a'\] :pre - -The variable value can then be easily read and written by accessing the value -property of this object. - -print(a.value) -a.value = 4 :pre - -Retrieving the value of an arbitrary LAMMPS expressions :h4 - -LAMMPS expressions can be immediately evaluated by using the eval method. The -passed string parameter can be any expression containing global thermo values, -variables, compute or fix data. - -result = L.eval("ke") # kinetic energy -result = L.eval("pe") # potential energy :pre - -result = L.eval("v_t/2.0") :pre - -Accessing atom data :h4 - -All atoms in the current simulation can be accessed by using the L.atoms list. -Each element of this list is an object which exposes its properties (id, type, -position, velocity, force, etc.). - -# access first atom -L.atoms\[0\].id -L.atoms\[0\].type :pre - -# access second atom -L.atoms\[1\].position -L.atoms\[1\].velocity -L.atoms\[1\].force :pre - -Some properties can also be used to set: - -# set position in 2D simulation -L.atoms\[0\].position = (1.0, 0.0) :pre - -# set position in 3D simulation -L.atoms\[0\].position = (1.0, 0.0, 1.) :pre - -Evaluating thermo data :h4 - -Each simulation run usually produces thermo output based on system state, -computes, fixes or variables. The trajectories of these values can be queried -after a run via the L.runs list. This list contains a growing list of run data. -The first element is the output of the first run, the second element that of -the second run. - -L.run(1000) -L.runs\[0\] # data of first 1000 time steps :pre - -L.run(1000) -L.runs\[1\] # data of second 1000 time steps :pre - -Each run contains a dictionary of all trajectories. Each trajectory is -accessible through its thermo name: - -L.runs\[0\].step # list of time steps in first run -L.runs\[0\].ke # list of kinetic energy values in first run :pre - -Together with matplotlib plotting data out of LAMMPS becomes simple: - -import matplotlib.plot as plt - -steps = L.runs\[0\].step -ke = L.runs\[0\].ke -plt.plot(steps, ke) :pre - -Error handling with PyLammps :h4 - -Compiling the shared library with C++ exception support provides a better error -handling experience. Without exceptions the LAMMPS code will terminate the -current Python process with an error message. C++ exceptions allow capturing -them on the C++ side and rethrowing them on the Python side. This way you -can handle LAMMPS errors through the Python exception handling mechanism. - -IMPORTANT NOTE: Capturing a LAMMPS exception in Python can still mean that the -current LAMMPS process is in an illegal state and must be terminated. It is -advised to save your data and terminate the Python instance as quickly as -possible. - -Using PyLammps in IPython notebooks and Jupyter :h4 - -If the LAMMPS Python package is installed for the same Python interpreter as -IPython, you can use PyLammps directly inside of an IPython notebook inside of -Jupyter. Jupyter is a powerful integrated development environment (IDE) for -many dynamic languages like Python, Julia and others, which operates inside of -any web browser. Besides auto-completion and syntax highlighting it allows you -to create formatted documents using Markup, mathematical formulas, graphics and -animations intermixed with executable Python code. It is a great format for -tutorials and showcasing your latest research. - -To launch an instance of Jupyter simply run the following command inside your -Python environment (this assumes you followed the Quick Start instructions): - -jupyter notebook :pre - -IPyLammps Examples :h4 - -Examples of IPython notebooks can be found in the python/examples/pylammps -sub-directory. To open these notebooks launch {jupyter notebook} inside this -directory and navigate to one of them. If you compiled and installed -a LAMMPS shared library with exceptions, PNG, JPEG and FFMPEG support -you should be able to rerun all of these notebooks. - -Validating a dihedral potential :h5 - -This example showcases how an IPython Notebook can be used to compare a simple -LAMMPS simulation of a harmonic dihedral potential to its analytical solution. -Four atoms are placed in the simulation and the dihedral potential is applied on -them using a datafile. Then one of the atoms is rotated along the central axis by -setting its position from Python, which changes the dihedral angle. - -phi = \[d * math.pi / 180 for d in range(360)\] :pre - -pos = \[(1.0, math.cos(p), math.sin(p)) for p in phi\] :pre - -pe = \[\] -for p in pos: - L.atoms\[3\].position = p - L.run(0) - pe.append(L.eval("pe")) :pre - -By evaluating the potential energy for each position we can verify that -trajectory with the analytical formula. To compare both solutions, we plot -both trajectories over each other using matplotlib, which embeds the generated -plot inside the IPython notebook. - -:c,image(JPG/pylammps_dihedral.jpg) - -Running a Monte Carlo relaxation :h5 - -This second example shows how to use PyLammps to create a 2D Monte Carlo Relaxation -simulation, computing and plotting energy terms and even embedding video output. - -Initially, a 2D system is created in a state with minimal energy. - -:c,image(JPG/pylammps_mc_minimum.jpg) - -It is then disordered by moving each atom by a random delta. - -random.seed(27848) -deltaperturb = 0.2 :pre - -for i in range(L.system.natoms): - x, y = L.atoms\[i\].position - dx = deltaperturb * random.uniform(-1, 1) - dy = deltaperturb * random.uniform(-1, 1) - L.atoms\[i\].position = (x+dx, y+dy) :pre - -L.run(0) :pre - -:c,image(JPG/pylammps_mc_disordered.jpg) - -Finally, the Monte Carlo algorithm is implemented in Python. It continuously -moves random atoms by a random delta and only accepts certain moves. - -estart = L.eval("pe") -elast = estart :pre - -naccept = 0 -energies = \[estart\] :pre - -niterations = 3000 -deltamove = 0.1 -kT = 0.05 :pre - -natoms = L.system.natoms :pre - -for i in range(niterations): - iatom = random.randrange(0, natoms) - current_atom = L.atoms\[iatom\] :pre - - x0, y0 = current_atom.position :pre - - dx = deltamove * random.uniform(-1, 1) - dy = deltamove * random.uniform(-1, 1) :pre - - current_atom.position = (x0+dx, y0+dy) :pre - - L.run(1, "pre no post no") :pre - - e = L.eval("pe") - energies.append(e) :pre - - if e <= elast: - naccept += 1 - elast = e - elif random.random() <= math.exp(natoms*(elast-e)/kT): - naccept += 1 - elast = e - else: - current_atom.position = (x0, y0) :pre - -The energies of each iteration are collected in a Python list and finally plotted using matplotlib. - -:c,image(JPG/pylammps_mc_energies_plot.jpg) - -The IPython notebook also shows how to use dump commands and embed video files -inside of the IPython notebook. - -Using PyLammps and mpi4py (Experimental) :h4 - -PyLammps can be run in parallel using mpi4py. This python package can be installed using - -pip install mpi4py :pre - -The following is a short example which reads in an existing LAMMPS input file and -executes it in parallel. You can find in.melt in the examples/melt folder. - -from mpi4py import MPI -from lammps import PyLammps :pre - -L = PyLammps() -L.file("in.melt") :pre - -if MPI.COMM_WORLD.rank == 0: - print("Potential energy: ", L.eval("pe")) :pre - -MPI.Finalize() :pre - -To run this script (melt.py) in parallel using 4 MPI processes we invoke the -following mpirun command: - -mpirun -np 4 python melt.py :pre - -IMPORTANT NOTE: Any command must be executed by all MPI processes. However, evaluations and querying the system state is only available on rank 0. - -Feedback and Contributing :h4 - -If you find this Python interface useful, please feel free to provide feedback -and ideas on how to improve it to Richard Berger (richard.berger@temple.edu). We also -want to encourage people to write tutorial style IPython notebooks showcasing LAMMPS usage -and maybe their latest research results.