python: doc and example updates

This commit is contained in:
Richard Berger
2024-11-24 01:36:01 -07:00
committed by Richard Berger
parent e45ef5adc0
commit 754aa1c73f
16 changed files with 206 additions and 466 deletions

View File

@ -104,6 +104,5 @@ Tutorials howto
Howto_lammps_gui
Howto_moltemplate
Howto_pylammps
Howto_python
Howto_wsl

View File

@ -3,4 +3,4 @@ PyLammps Tutorial
The PyLammps interface is deprecated and will be removed in a future release of
LAMMPS. As such, the PyLammps version of this tutorial has been removed and is
replaced by the :doc:`Howto_python`.
replaced by the :doc:`Python_head`.

View File

@ -26,14 +26,30 @@ against invalid accesses.
lmp = lammps()
lmp.file("in.sysinit")
# Read/Write access via ctypes
nlocal = lmp.extract_global("nlocal")
x = lmp.extract_atom("x")
for i in range(nlocal):
print("(x,y,z) = (", x[i][0], x[i][1], x[i][2], ")")
# Read/Write access via NumPy arrays
atom_id = L.numpy.extract_atom("id")
atom_type = L.numpy.extract_atom("type")
x = L.numpy.extract_atom("x")
v = L.numpy.extract_atom("v")
f = L.numpy.extract_atom("f")
# set position in 2D simulation
x[0] = (1.0, 0.0)
# set position in 3D simulation
x[0] = (1.0, 0.0, 1.)
lmp.close()
**Methods**:
* :py:meth:`extract_atom() <lammps.lammps.extract_atom()>`: extract a per-atom quantity

View File

@ -6,11 +6,10 @@ Creating or deleting a LAMMPS object
====================================
With the Python interface the creation of a :cpp:class:`LAMMPS
<LAMMPS_NS::LAMMPS>` instance is included in the constructors for the
:py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>`,
and :py:class:`IPyLammps <lammps.IPyLammps>` classes.
Internally it will call either :cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C
library API to create the class instance.
<LAMMPS_NS::LAMMPS>` instance is included in the constructor for the
:py:class:`lammps <lammps.lammps>` class. Internally it will call either
:cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C library
API to create the class instance.
All arguments are optional. The *name* argument allows loading a
LAMMPS shared library that is named ``liblammps_machine.so`` instead of

View File

@ -26,7 +26,7 @@ demonstrates the use of :py:func:`lammps.file()`, :py:func:`lammps.command()`,
lmp.command('variable zpos index 1.0')
# create 10 groups with 10 atoms each
cmds = ["group g{} id {}:{}".format(i,10*i+1,10*(i+1)) for i in range(10)]
cmds = [f"group g{i} id {10*i+1}:{10*(i+1)}" for i in range(10)]
lmp.commands_list(cmds)
# run commands from a multi-line string
@ -38,10 +38,9 @@ demonstrates the use of :py:func:`lammps.file()`, :py:func:`lammps.command()`,
"""
lmp.commands_string(block)
Unlike the lammps API, the PyLammps/IPyLammps APIs allow running LAMMPS
commands by calling equivalent member functions of :py:class:`PyLammps <lammps.PyLammps>`
and :py:class:`IPyLammps <lammps.IPyLammps>` instances.
For convenience, the :py:class:`lammps <lammps.lammps>` class also provides a
command wrapper ``cmd`` that turns any LAMMPS command into a regular function
call.
For instance, the following LAMMPS command
@ -49,8 +48,7 @@ For instance, the following LAMMPS command
region box block 0 10 0 5 -0.5 0.5
can be executed using with the lammps API with the following Python code if ``lmp`` is an
instance of :py:class:`lammps <lammps.lammps>`:
would normally be executed with the following Python code:
.. code-block:: python
@ -59,7 +57,7 @@ instance of :py:class:`lammps <lammps.lammps>`:
lmp = lammps()
lmp.command("region box block 0 10 0 5 -0.5 0.5")
With the PyLammps interface, any LAMMPS command can be split up into arbitrary parts.
With the ``cmd`` wrapper, any LAMMPS command can be split up into arbitrary parts.
These parts are then passed to a member function with the name of the :doc:`command <Commands_all>`.
For the :doc:`region <region>` command that means the :code:`region()` method can be called.
The arguments of the command can be passed as one string, or
@ -82,25 +80,31 @@ member function takes the entire parameter list and transparently merges it to a
string.
The benefit of this approach is avoiding redundant command calls and easier
parameterization. In the lammps API parameterization needed to be done
manually by creating formatted command strings.
parameterization. With `command`, `commands_list`, and `commands_string` the
parameterization needed to be done manually by creating formatted command
strings.
.. code-block:: python
lmp.command("region box block %f %f %f %f %f %f" % (xlo, xhi, ylo, yhi, zlo, zhi))
In contrast, methods of PyLammps accept parameters directly and will convert
In contrast, methods of the `cmd` wrapper accept parameters directly and will convert
them automatically to a final command string.
.. code-block:: python
L.cmd.region("box block", xlo, xhi, ylo, yhi, zlo, zhi)
.. note::
When running in IPython you can use Tab-completion after ``L.cmd.`` to see
all available LAMMPS commands.
Using these facilities, the previous example shown above can be rewritten as follows:
.. code-block:: python
from lammps import PyLammps
from lammps import lammps
L = lammps()
# read commands from file 'in.melt'

View File

@ -15,6 +15,7 @@ together.
Python_call
Python_formats
Python_examples
Python_jupyter
Python_error
Python_trouble

View File

@ -0,0 +1,48 @@
Using LAMMPS in IPython notebooks and Jupyter
=============================================
If the LAMMPS Python package is installed for the same Python interpreter as
`IPython <ipython>`_, you can use LAMMPS directly inside of an IPython notebook inside of
Jupyter. `Jupyter <juypter>`_ 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.
The easiest way to install it is via ``pip``:
.. code-block:: bash
pip install jupyter
To launch an instance of Jupyter simply run the following command inside your
Python environment:
.. code-block:: bash
jupyter notebook
.. _ipython: https://ipython.org/
.. _jupyter: https://jupyter.org/
Interactive Python Examples
---------------------------
Examples of IPython notebooks can be found in the ``python/examples/ipython``
subdirectory. They require LAMMPS to be compiled as shared library with PYTHON,
PNG, JPEG and FFMPEG support.
To open these notebooks launch ``jupyter notebook index.ipynb`` inside this
directory. The opened file provides an overview of the available examples.
- Example 1: Using LAMMPS with Python (``simple.ipynb``)
- Example 2: Analyzing LAMMPS thermodynamic data (``thermo.ipynb``)
- Example 3: Working with Per-Atom Data (``atoms.ipynb``)
- Example 4: Working with LAMMPS variables (``variables.ipynb``)
- Example 5: Validating a dihedral potential (``dihedrals/dihedral.ipynb``)
- Example 6: Running a Monte Carlo relaxation (``montecarlo/mc.ipynb``)
.. note::
Typically clicking a link in Jupyter will open a new tab, which might be blocked by your pop-up blocker.

View File

@ -14,9 +14,7 @@ session with the ``import`` command.
Alternative interfaces such as :py:class:`PyLammps <lammps.PyLammps>` and
:py:class:`IPyLammps <lammps.IPyLammps>` classes have been deprecated and
will be removed in a future version of LAMMPS. The :doc:`Howto_pylammps` has
also been replaced by a reworked :doc:`Howto_python` that showcases how to
use the modern Python API facilities instead.
will be removed in a future version of LAMMPS.
.. _mpi4py_url: https://mpi4py.readthedocs.io

View File

@ -4,10 +4,6 @@ Compute, fixes, variables
This section documents accessing or modifying data from objects like
computes, fixes, or variables in LAMMPS using the :py:mod:`lammps` module.
.. tabs::
.. tab:: lammps API
For :py:meth:`lammps.extract_compute() <lammps.lammps.extract_compute()>` and
:py:meth:`lammps.extract_fix() <lammps.lammps.extract_fix()>`, the global, per-atom,
or local data calculated by the compute or fix can be accessed. What is returned
@ -57,42 +53,3 @@ computes, fixes, or variables in LAMMPS using the :py:mod:`lammps` module.
* :py:meth:`lammps.numpy.extract_compute() <lammps.numpy_wrapper.numpy_wrapper.extract_compute()>`: extract value(s) from a compute, return arrays as numpy arrays
* :py:meth:`lammps.numpy.extract_fix() <lammps.numpy_wrapper.numpy_wrapper.extract_fix()>`: extract value(s) from a fix, return arrays as numpy arrays
* :py:meth:`lammps.numpy.extract_variable() <lammps.numpy_wrapper.numpy_wrapper.extract_variable()>`: extract value(s) from a variable, return arrays as numpy arrays
.. tab:: PyLammps/IPyLammps API
PyLammps and IPyLammps classes currently do not add any additional ways of
retrieving information out of computes and fixes. This information can still be accessed by using the lammps API:
.. code-block:: python
L.lmp.extract_compute(...)
L.lmp.extract_fix(...)
# OR
L.lmp.numpy.extract_compute(...)
L.lmp.numpy.extract_fix(...)
LAMMPS variables can be both defined and accessed via the :py:class:`PyLammps <lammps.PyLammps>` interface.
To define a variable you can use the :doc:`variable <variable>` command:
.. code-block:: python
L.variable("a index 2")
A dictionary of all variables is returned by the :py:attr:`PyLammps.variables <lammps.PyLammps.variables>` property:
you can access an individual variable by retrieving a variable object from the
``L.variables`` dictionary by name
.. code-block:: python
a = L.variables['a']
The variable value can then be easily read and written by accessing the value
property of this object.
.. code-block:: python
print(a.value)
a.value = 4

View File

@ -2,14 +2,8 @@ System properties
=================
Similar to what is described in :doc:`Library_properties`, the instances of
:py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>`, or
:py:class:`IPyLammps <lammps.IPyLammps>` can be used to extract different kinds
of information about the active LAMMPS instance and also to modify some of it. The
main difference between the interfaces is how the information is exposed.
While the :py:class:`lammps <lammps.lammps>` is just a thin layer that wraps C API calls,
:py:class:`PyLammps <lammps.PyLammps>` and :py:class:`IPyLammps <lammps.IPyLammps>` expose
information as objects and properties.
:py:class:`lammps <lammps.lammps>` can be used to extract different kinds
of information about the active LAMMPS instance and also to modify some of it.
In some cases the data returned is a direct reference to the original data
inside LAMMPS cast to ``ctypes`` pointers. Where possible, the wrappers will
@ -25,10 +19,6 @@ against invalid accesses.
accordingly. These arrays can change sizes and order at every neighbor list
rebuild and atom sort event as atoms are migrating between subdomains.
.. tabs::
.. tab:: lammps API
.. code-block:: python
from lammps import lammps
@ -64,74 +54,3 @@ against invalid accesses.
**Properties**:
* :py:attr:`last_thermo_step <lammps.lammps.last_thermo_step>`: the last timestep thermodynamic output was computed
.. tab:: PyLammps/IPyLammps API
In addition to the functions provided by :py:class:`lammps <lammps.lammps>`, :py:class:`PyLammps <lammps.PyLammps>` objects
have several properties which allow you to query the system state:
L.system
Is a dictionary describing the system such as the bounding box or number of atoms
L.system.xlo, L.system.xhi
bounding box limits along x-axis
L.system.ylo, L.system.yhi
bounding box limits along y-axis
L.system.zlo, L.system.zhi
bounding box limits along z-axis
L.communication
configuration of communication subsystem, such as the number of threads or processors
L.communication.nthreads
number of threads used by each LAMMPS process
L.communication.nprocs
number of MPI processes used by LAMMPS
L.fixes
List of fixes in the current system
L.computes
List of active computes in the current system
L.dump
List of active dumps in the current system
L.groups
List of groups present in the current system
**Retrieving the value of an arbitrary LAMMPS expressions**
LAMMPS expressions can be immediately evaluated by using the ``eval`` method. The
passed string parameter can be any expression containing global :doc:`thermo` values,
variables, compute or fix data (see :doc:`Howto_output`):
.. code-block:: python
result = L.eval("ke") # kinetic energy
result = L.eval("pe") # potential energy
result = L.eval("v_t/2.0")
**Example**
.. code-block:: python
from lammps import PyLammps
L = PyLammps()
L.file("in.sysinit")
print(f"running simulation with {L.system.natoms} atoms")
L.run(1000, "post no");
for i in range(10):
L.run(100, "pre no post no")
pe = L.eval("pe")
ke = L.eval("ke")
print(f"PE = {pe}\nKE = {ke}")

View File

@ -4,7 +4,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 3: Example 3: Using Atom Data"
"<div style=\"text-align: center\"><a href=\"index.ipynb\">LAMMPS Python Tutorials</a></div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 3: Working with Per-Atom Data"
]
},
{
@ -133,248 +140,6 @@
"L.ipython.image(zoom=1.8)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Queries about LAMMPS simulation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.system"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.system.natoms"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.system.nbonds"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.system.nbondtypes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.communication"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.fixes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.computes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.dumps"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.groups"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Working with LAMMPS Variables"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variable(\"a index 2\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variables"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variable(\"t equal temp\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variables"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"\n",
"if sys.version_info < (3, 0):\n",
" # In Python 2 'print' is a restricted keyword, which is why you have to use the lmp_print function instead.\n",
" x = float(L.lmp_print('\"${a}\"'))\n",
"else:\n",
" # In Python 3 the print function can be redefined.\n",
" # x = float(L.print('\"${a}\"')\")\n",
" \n",
" # To avoid a syntax error in Python 2 executions of this notebook, this line is packed into an eval statement\n",
" x = float(eval(\"L.print('\\\"${a}\\\"')\"))\n",
"x"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variables['t'].value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.eval(\"v_t/2.0\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variable(\"b index a b c\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variables['b'].value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.eval(\"v_b\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variables['b'].definition"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variable(\"i loop 10\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.variables['i'].value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.next(\"i\")\n",
"L.variables['i'].value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"L.expand(\"ke\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -451,7 +216,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.7"
}
},
"nbformat": 4,

View File

@ -4,7 +4,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Validating a dihedral potential"
"<div style=\"text-align: center\"><a href=\"../index.ipynb\">LAMMPS Python Tutorials</a></div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 4: Validating a dihedral potential"
]
},
{
@ -232,7 +239,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.7"
}
},
"nbformat": 4,

View File

@ -5,7 +5,7 @@
"id": "666d3036-47d5-44d2-bc1a-ca4b00a9e9b8",
"metadata": {},
"source": [
"# LAMMPS IPython Tutorial"
"# LAMMPS Python Tutorials"
]
},
{
@ -25,7 +25,9 @@
"\n",
"- [Example 1: Using LAMMPS with Python](simple.ipynb)\n",
"- [Example 2: Analyzing LAMMPS thermodynamic data](thermo.ipynb)\n",
"- [Example 3: Using Atom Data](atom.ipynb)"
"- [Example 3: Using Atom Data](atoms.ipynb)\n",
"- [Example 4: Validating a dihedral potential](dihedrals/dihedral.ipynb)\n",
"- [Example 5: Running a Monte Carlo relaxation](montecarlo/mc.ipynb)"
]
},
{
@ -53,7 +55,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.7"
}
},
"nbformat": 4,

View File

@ -4,7 +4,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Monte Carlo Relaxation"
"<div style=\"text-align: center\"><a href=\"../index.ipynb\">LAMMPS Python Tutorials</a></div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example 5: Monte Carlo Relaxation"
]
},
{
@ -343,7 +350,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.7"
}
},
"nbformat": 4,

View File

@ -298,7 +298,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.7"
}
},
"nbformat": 4,

View File

@ -279,6 +279,24 @@
"source": [
"current_run.plot(x='Step', y='TotEng')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Conclusion\n",
"\n",
"The Python interface gives you a powerful way of invoking and extracting simulation data while the simulation is running. Next we'll look at how to extract information about the atoms in your system.\n",
"\n",
"<div style=\"text-align:right\"><a href=\"atoms.ipynb\">Next</a>"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@ -297,7 +315,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
"version": "3.12.7"
}
},
"nbformat": 4,