Merge pull request #4470 from akohlmey/bye-bye-python-zwei

Remove support for Python 2.x and show corresponding errors.
This commit is contained in:
Axel Kohlmeyer
2025-02-13 19:44:07 -05:00
committed by GitHub
28 changed files with 197 additions and 197 deletions

View File

@ -225,6 +225,12 @@ if(DEFINED ENV{VIRTUAL_ENV} AND NOT Python_EXECUTABLE)
" Setting Python interpreter to: ${Python_EXECUTABLE}") " Setting Python interpreter to: ${Python_EXECUTABLE}")
endif() endif()
find_package(Python COMPONENTS Interpreter QUIET)
# NOTE: RHEL 8.0 and Ubuntu 18.04LTS ship with Python 3.6, Python 3.8 was EOL in 2024
if(Python_VERSION VERSION_LESS 3.6)
message(FATAL_ERROR "LAMMPS requires Python 3.6 or later")
endif()
set(LAMMPS_MACHINE "" CACHE STRING "Suffix to append to lmp binary (WON'T enable any features automatically") set(LAMMPS_MACHINE "" CACHE STRING "Suffix to append to lmp binary (WON'T enable any features automatically")
mark_as_advanced(LAMMPS_MACHINE) mark_as_advanced(LAMMPS_MACHINE)
if(LAMMPS_MACHINE) if(LAMMPS_MACHINE)

View File

@ -1,11 +1,11 @@
# use default (or custom) Python executable, if version is sufficient # use default (or custom) Python executable.
if(Python_VERSION VERSION_GREATER_EQUAL 3.6) # Python version check is in main CMakeLists.txt file
if(Python_EXECUTABLE)
set(Python3_EXECUTABLE ${Python_EXECUTABLE}) set(Python3_EXECUTABLE ${Python_EXECUTABLE})
endif() endif()
find_package(Python3 COMPONENTS Interpreter) find_package(Python3 COMPONENTS Interpreter)
if(Python3_EXECUTABLE) if(Python3_EXECUTABLE)
if(Python3_VERSION VERSION_GREATER_EQUAL 3.6)
add_custom_target( add_custom_target(
check-whitespace check-whitespace
${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py . ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py .
@ -36,5 +36,4 @@ if(Python3_EXECUTABLE)
${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f . ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f .
WORKING_DIRECTORY ${LAMMPS_DIR} WORKING_DIRECTORY ${LAMMPS_DIR}
COMMENT "Fix permission errors") COMMENT "Fix permission errors")
endif()
endif() endif()

View File

@ -24,9 +24,7 @@ if(MLIAP_ENABLE_PYTHON)
if(NOT PKG_PYTHON) if(NOT PKG_PYTHON)
message(FATAL_ERROR "Must enable PYTHON package for including Python support in ML-IAP") message(FATAL_ERROR "Must enable PYTHON package for including Python support in ML-IAP")
endif() endif()
if(Python_VERSION VERSION_LESS 3.6) # Python version check is in main CMakeLists.txt file
message(FATAL_ERROR "Python support in ML-IAP requires Python 3.6 or later")
endif()
set(MLIAP_BINARY_DIR ${CMAKE_BINARY_DIR}/cython) set(MLIAP_BINARY_DIR ${CMAKE_BINARY_DIR}/cython)
file(GLOB MLIAP_CYTHON_SRC CONFIGURE_DEPENDS ${LAMMPS_SOURCE_DIR}/ML-IAP/*.pyx) file(GLOB MLIAP_CYTHON_SRC CONFIGURE_DEPENDS ${LAMMPS_SOURCE_DIR}/ML-IAP/*.pyx)

View File

@ -1139,11 +1139,10 @@ POEMS package
PYTHON package PYTHON package
--------------------------- ---------------------------
Building with the PYTHON package requires you have a the Python development Building with the PYTHON package requires you have a the Python
headers and library available on your system, which needs to be a Python 2.7 development headers and library available on your system, which
version or a Python 3.x version. Since support for Python 2.x has ended, needs to be Python version 3.6 or later. See ``lib/python/README``
using Python 3.x is strongly recommended. See ``lib/python/README`` for for additional details.
additional details.
.. tabs:: .. tabs::
@ -1159,7 +1158,7 @@ additional details.
set the Python_EXECUTABLE variable to specify which Python set the Python_EXECUTABLE variable to specify which Python
interpreter should be used. Note note that you will also need to interpreter should be used. Note note that you will also need to
have the development headers installed for this version, have the development headers installed for this version,
e.g. python2-devel. e.g. python3-devel.
.. tab:: Traditional make .. tab:: Traditional make

View File

@ -30,9 +30,9 @@ additional tools to be available and functioning.
* A Bourne shell compatible "Unix" shell program (frequently this is ``bash``) * A Bourne shell compatible "Unix" shell program (frequently this is ``bash``)
* A few shell utilities: ``ls``, ``mv``, ``ln``, ``rm``, ``grep``, ``sed``, ``tr``, ``cat``, ``touch``, ``diff``, ``dirname`` * A few shell utilities: ``ls``, ``mv``, ``ln``, ``rm``, ``grep``, ``sed``, ``tr``, ``cat``, ``touch``, ``diff``, ``dirname``
* Python (optional, required for ``make lib-<pkg>`` in the ``src`` * Python (optional, required for ``make lib-<pkg>`` in the ``src``
folder). Python scripts are currently tested with python 2.7 and folder). Python scripts are currently tested with 3.6 to 3.11.
3.6 to 3.11. The procedure for :doc:`building the documentation The procedure for :doc:`building the documentation <Build_manual>`
<Build_manual>` *requires* Python 3.5 or later. *requires* Python 3.8 or later.
Getting started Getting started
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^

View File

@ -162,7 +162,7 @@ are usually installed by default, the following packages are required:
- dvipng - dvipng
- ellipse - ellipse
- fncychap - fncychap
- fontawesom - fontawesome
- framed - framed
- geometry - geometry
- gyre - gyre

View File

@ -13,10 +13,14 @@ Programming language standards
Most of the C++ code currently requires a compiler compatible with the Most of the C++ code currently requires a compiler compatible with the
C++11 standard, the KOKKOS package currently requires C++17. Most of C++11 standard, the KOKKOS package currently requires C++17. Most of
the Python code is written to be compatible with Python 3.5 or later or the Python code is written to be compatible with Python 3.6 or later.
Python 2.7. Some Python scripts *require* Python 3 and a few others
still need to be ported from Python 2 to Python 3.
.. deprecated:: TBD
Python 2.x is no longer supported and trying to use it, e.g. for the
LAMMPS Python module should result in an error. If you come across
some part of the LAMMPS distribution that is not (yet) compatible with
Python 3, please notify the LAMMPS developers.
Build systems Build systems
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -24,8 +28,8 @@ Build systems
LAMMPS can be compiled from source code using a (traditional) build LAMMPS can be compiled from source code using a (traditional) build
system based on shell scripts, a few shell utilities (grep, sed, cat, system based on shell scripts, a few shell utilities (grep, sed, cat,
tr) and the GNU make program. This requires running within a Bourne tr) and the GNU make program. This requires running within a Bourne
shell (``/bin/sh``). Alternatively, a build system with different back ends shell (``/bin/sh``). Alternatively, a build system with different back
can be created using CMake. CMake must be at least version 3.16. ends can be created using CMake. CMake must be at least version 3.16.
Operating systems Operating systems
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

View File

@ -189,10 +189,8 @@ of the contribution. As of January 2023, all previously included
Fortran code for the LAMMPS executable has been replaced by equivalent Fortran code for the LAMMPS executable has been replaced by equivalent
C++ code. C++ code.
Python code must be compatible with Python 3.5 and later. Large parts Python code currently must be compatible with Python 3.6. If a later
of LAMMPS (including the :ref:`PYTHON package <PKG-PYTHON>`) are also version or Python is required, it needs to be documented.
compatible with Python 2.7. Compatibility with Python 2.7 is desirable,
but compatibility with Python 3.5 is **required**.
Compatibility with older programming language standards is very Compatibility with older programming language standards is very
important to maintain portability and availability of LAMMPS on many important to maintain portability and availability of LAMMPS on many

View File

@ -2428,7 +2428,7 @@ ways to use LAMMPS and Python together.
Building with the PYTHON package assumes you have a Python development Building with the PYTHON package assumes you have a Python development
environment (headers and libraries) available on your system, which needs environment (headers and libraries) available on your system, which needs
to be either Python version 2.7 or Python 3.5 and later. to be Python version 3.6 or later.
**Install:** **Install:**

View File

@ -7,6 +7,10 @@ LAMMPS shared library through the Python `ctypes <ctypes_>`_
module. Because of the dynamic loading, it is required that LAMMPS is module. Because of the dynamic loading, it is required that LAMMPS is
compiled in :ref:`"shared" mode <exe>`. compiled in :ref:`"shared" mode <exe>`.
.. versionchanged:: TBD
LAMMPS currently only supports Python version 3.6 or later.
Two components are necessary for Python to be able to invoke LAMMPS code: Two components are necessary for Python to be able to invoke LAMMPS code:
* The LAMMPS Python Package (``lammps``) from the ``python`` folder * The LAMMPS Python Package (``lammps``) from the ``python`` folder
@ -136,11 +140,6 @@ folder that the dynamic loader searches or inside of the installed
# create virtual environment in folder $HOME/myenv # create virtual environment in folder $HOME/myenv
python3 -m venv $HOME/myenv python3 -m venv $HOME/myenv
For Python versions prior 3.3 you can use `virtualenv
<https://packaging.python.org/en/latest/key_projects/#virtualenv>`_
command instead of "python3 -m venv". This step has to be done
only once.
To activate the virtual environment type: To activate the virtual environment type:
.. code-block:: bash .. code-block:: bash
@ -245,14 +244,14 @@ make MPI calls directly from Python in your script, if you desire.
We have tested this with `MPI for Python <https://mpi4py.readthedocs.io/>`_ We have tested this with `MPI for Python <https://mpi4py.readthedocs.io/>`_
(aka mpi4py) and you will find installation instruction for it below. (aka mpi4py) and you will find installation instruction for it below.
Installation of mpi4py (version 3.0.3 as of Sep 2020) can be done as Installation of mpi4py (version 4.0.1 as of Feb 2025) can be done as
follows: follows:
- Via ``pip`` into a local user folder with: - Via ``pip`` into a local user folder with:
.. code-block:: bash .. code-block:: bash
pip install --user mpi4py python3 -m pip install --user mpi4py
- Via ``dnf`` into a system folder for RedHat/Fedora systems: - Via ``dnf`` into a system folder for RedHat/Fedora systems:
@ -261,20 +260,20 @@ follows:
# for use with OpenMPI # for use with OpenMPI
sudo dnf install python3-mpi4py-openmpi sudo dnf install python3-mpi4py-openmpi
# for use with MPICH # for use with MPICH
sudo dnf install python3-mpi4py-openmpi sudo dnf install python3-mpi4py-mpich
- Via ``pip`` into a virtual environment (see above): - Via ``pip`` into a virtual environment (see above):
.. code-block:: console .. code-block:: console
$ source $HOME/myenv/activate $ source $HOME/myenv/activate
(myenv)$ pip install mpi4py (myenv)$ python -m pip install mpi4py
- Via ``pip`` into a system folder (not recommended): - Via ``pip`` into a system folder (not recommended):
.. code-block:: bash .. code-block:: bash
sudo pip install mpi4py sudo python3 -m pip install mpi4py
For more detailed installation instructions and additional options, For more detailed installation instructions and additional options,
please see the `mpi4py installation <https://mpi4py.readthedocs.io/en/stable/install.html>`_ page. please see the `mpi4py installation <https://mpi4py.readthedocs.io/en/stable/install.html>`_ page.

View File

@ -44,15 +44,11 @@ Below is an example output for Python version 3.8.5.
.. warning:: .. warning::
The options described in this section of the manual for using Python The options described in this section of the manual for using Python
with LAMMPS currently support either Python 2 or 3. Specifically with LAMMPS support only Python 3.6 or later. For use with Python
version 2.7 or later and 3.6 or later. Since the Python community no 2.x you will need to use an older LAMMPS version like 29 Aug 2024
longer maintains Python 2 (see `this notice or older. If you notice Python code in the LAMMPS distribution that
<https://www.python.org/doc/sunset-python-2/>`_), we recommend use of is not compatible with Python 3, please contact the LAMMPS developers
Python 3 with LAMMPS. While Python 2 code should continue to work, or submit `and issue on GitHub <https://github.com/lammps/lammps/issues>`_
that is not something we can guarantee long-term. If you notice
Python code in the LAMMPS distribution that is not compatible with
Python 3, please contact the LAMMPS developers or submit `and issue
on GitHub <https://github.com/lammps/lammps/issues>`_
--------- ---------

View File

@ -166,11 +166,7 @@ Only the following region styles are currently supported: *block*,
*cone*, *cylinder*, *ellipsoid*, *prism*, and *sphere*. Regions formed *cone*, *cylinder*, *ellipsoid*, *prism*, and *sphere*. Regions formed
from unions or intersections of other regions are not supported. from unions or intersections of other regions are not supported.
For region style *cone* one of the two radii must be zero, since the Rotating regions are currently not supported.
equivalent VMD graphics primitive does not support truncated cones.
Also the VMD graphics primitive does not support open cones.
Rotating regions are not supported.
Related commands Related commands
"""""""""""""""" """"""""""""""""

View File

@ -99,6 +99,7 @@ AMD
amino amino
Amirjalayer Amirjalayer
Amit Amit
amsmath
amu amu
Amzallag Amzallag
analytical analytical
@ -128,6 +129,7 @@ Antisymmetrized
antisymmetry antisymmetry
anton anton
Antonelli Antonelli
anysize
api api
apolar apolar
Apoorva Apoorva
@ -613,6 +615,7 @@ Courant
covalent covalent
covalently covalently
covariance covariance
cp
cpp cpp
cpu cpu
cradius cradius
@ -905,6 +908,7 @@ dUs
Duval Duval
dV dV
dvector dvector
dvipng
dVx dVx
dW dW
dx dx
@ -1215,12 +1219,14 @@ fmz
fN fN
Fn Fn
fname fname
fncychap
fno fno
Fnudge Fnudge
foces foces
Fock Fock
Fogarty Fogarty
Foiles Foiles
fontawesome
fopenmp fopenmp
forceclear forceclear
forestgreen forestgreen
@ -1407,6 +1413,7 @@ Gunsteren
Gunzenmuller Gunzenmuller
Guo Guo
gw gw
gyre
gyromagnetic gyromagnetic
gz gz
gzip gzip
@ -1532,10 +1539,12 @@ hydrostatically
hydroxyl hydroxyl
Hynninen Hynninen
Hyoungki Hyoungki
hypcap
hyperdynamics hyperdynamics
hyperparameters hyperparameters
hyperplane hyperplane
hyperradius hyperradius
hyperref
hyperspherical hyperspherical
hysteretic hysteretic
hz hz
@ -2514,6 +2523,7 @@ Ndof
Ndouble Ndouble
ndx ndx
neb neb
needspace
neel neel
Neel Neel
Neelov Neelov
@ -2918,6 +2928,7 @@ picogram
picograms picograms
picosecond picosecond
picoseconds picoseconds
pict
pid pid
piecewise piecewise
Pieniazek Pieniazek
@ -3689,6 +3700,7 @@ Sz
Tabbernor Tabbernor
tabinner tabinner
tabstyle tabstyle
tabulary
Tadmor Tadmor
Tafipolsky Tafipolsky
tagID tagID
@ -3786,6 +3798,7 @@ timestamps
timestep timestep
timestepping timestepping
timesteps timesteps
titlesec
TiN TiN
TiO TiO
Tirado Tirado
@ -3962,6 +3975,7 @@ untilted
Unwin Unwin
uparrow uparrow
upenn upenn
upquote
upto upto
Urbakh Urbakh
Urbana Urbana
@ -4148,6 +4162,7 @@ Workum
Worley Worley
wormlike wormlike
wpbe wpbe
wrapfig
Wriggers Wriggers
writedata writedata
Wuppertal Wuppertal
@ -4178,6 +4193,7 @@ Xia
Xiaohu Xiaohu
Xiaowang Xiaowang
Xie Xie
xindy
xk xk
xlat xlat
xlattice xlattice

View File

@ -1,7 +0,0 @@
# Settings that the LAMMPS build will import when this package library is used
# See the README file for more explanation
python_SYSINC = $(shell which python2-config > /dev/null 2>&1 && python2-config --includes || (which python-config > /dev/null 2>&1 && python-config --includes || :))
python_SYSLIB = $(shell which python2-config > /dev/null 2>&1 && python2-config --ldflags || (which python-config > /dev/null 2>&1 && python-config --ldflags || :))
python_SYSPATH =
PYTHON=$(shell which python2 > /dev/null 2>&1 && echo python2 || echo python)

View File

@ -9,30 +9,29 @@ installation. If needed, you can copy one of the other provided
Makefile.lammps.* files to to Makefile.lammps before building Makefile.lammps.* files to to Makefile.lammps before building
LAMMPS itself. LAMMPS itself.
The files Makefile.lammps.python2 and Makefile.lammps.python3 are The file Makefile.lammps.python3 is similar to the default file, but
similar to the default file, but meant for the case that both, meant for the case that both, python 2 and python 3, are installed
python 2 and python 3, are installed simultaneously and you want simultaneously. LAMMPS only supports python 3. If neither of these
to prefer one over the other. If neither of these files work, you files work, you may have to create a custom Makefile.lammps file
may have to create a custom Makefile.lammps file suitable for suitable for the version of Python on your system. To illustrate, these
the version of Python on your system. To illustrate, these are are example settings from the Makefile.lammps.python3.13 file:
example settings from the Makefile.lammps.python2.7 file:
python_SYSINC = -I/usr/local/include/python2.7 python_SYSINC = -I/usr/local/include/python3.13
python_SYSLIB = -lpython2.7 -lnsl -ldl -lreadline -ltermcap -lpthread -lutil -lm python_SYSLIB = -lpython3.13 -ldl -lm
python_SYSPATH = python_SYSPATH = -L/usr/lib64
PYTHON=python2.7 PYTHON=python3.13
python_SYSINC refers to the directory where Python's Python.h file is python_SYSINC refers to the directory where Python's Python.h file is
found. LAMMPS includes this file. found. LAMMPS includes this file.
python_SYSLIB refers to the libraries needed to link to from an python_SYSLIB refers to the libraries needed to link to from an
application (LAMMPS in this case) to "embed" Python in the application (LAMMPS in this case) to "embed" Python in the
application. The Python library itself is listed (-lpython2.7) are application. The Python library itself is listed (-lpython3.13) are
are several system libraries needed by Python. are several system libraries needed by Python.
python_SYSPATH refers to the path (e.g. -L/usr/local/lib) where the python_SYSPATH refers to the path (e.g. -L/usr/local/lib) where the
Python library can be found. You may not need this setting if the Python library can be found. You may not need this setting if the
path is already included in your LD_LIBRARY_PATH environment variable. path is already included in your LIBRARY_PATH environment variable.
PYTHON is the name of the python interpreter. It is used for PYTHON is the name of the python interpreter. It is used for
installing the LAMMPS python module with "make install-python" installing the LAMMPS python module with "make install-python"
@ -45,7 +44,7 @@ run in embedded mode on your machine.
Here is what this Python doc page says about it: Here is what this Python doc page says about it:
https://docs.python.org/2/extending/embedding.html#compiling-and-linking-under-unix-like-systems https://docs.python.org/3/extending/embedding.html#compiling-and-linking-under-unix-like-systems
"It is not necessarily trivial to find the right flags to pass to your "It is not necessarily trivial to find the right flags to pass to your
compiler (and linker) in order to embed the Python interpreter into compiler (and linker) in order to embed the Python interpreter into

View File

@ -1,20 +1,27 @@
This directory contains Python code which wraps LAMMPS as a library This directory contains the LAMMPS Python module that allows the LAMMPS
and allows the LAMMPS library interface to be invoked from Python, C library interface to be invoked from Python, either from a Python
either from a Python script or using Python interactively. script or using Python interactively.
Details on the Python interface to LAMMPS and how to build LAMMPS as a Details on the Python interface to LAMMPS and how to build LAMMPS as a
shared library, for use with Python, are given in shared library, for use with Python, are given in
doc/Section_python.html and in doc/Section_start.html#start_5. https://docs.lammps.org/Build_basics.html#exe
and
https://docs.lammps.org/Python_install.html
Basically you need to follow these steps in the src directory: Basically you need to use the flag -D BUILD_SHARED_LIBS=ON when
configuring LAMMPS with CMake and then in the build folder use the
command % cmake --build . --target install-python
or for the legacy GNU build system execute these steps in the src folder:
% make g++ mode=shlib # build for whatever machine target you wish % make g++ mode=shlib # build for whatever machine target you wish
% make install-python # install into site-packages folder % make install-python # install into site-packages folder
You can replace the last step by a one-time setting of environment You can replace the last step by a one-time setting of environment
variables in your shell script. Or you can run the python/install.py variables in your shell environment. Or you can run the
script directly to give you more control over where the two relevant python/install.py script directly to give you more control over where
files are installed. See doc/Python_install.html for details. the two relevant files are installed. See
https://docs.lammps.org/Python_install.html for details.
You should then be able to launch Python and instantiate an instance You should then be able to launch Python and instantiate an instance
of LAMMPS: of LAMMPS:
@ -24,13 +31,14 @@ of LAMMPS:
>>> lmp = lammps() >>> lmp = lammps()
If that gives no errors, you have successfully wrapped LAMMPS with If that gives no errors, you have successfully wrapped LAMMPS with
Python. See doc/Section_python.html#py_7 for tests you can then use Python. See https://docs.lammps.org/Python_launch.html for examples how
to run LAMMPS both in serial or parallel thru Python. to run LAMMPS both in serial or parallel from Python.
Note that you can also invoke Python code from within a LAMMPS input Note that you can also invoke Python code from within a LAMMPS input
script, using the "python" command. See the doc/python.html doc page script, using the "python" command. See the
for details. The Python code you invoke can also call back to LAMMPS https://docs.lammps.org/python.html doc page for details. The Python
using the same interface described here for wrapping LAMMPS. code you invoke can also call back to LAMMPS using the same interface
described here for wrapping LAMMPS.
------------------------------------------------------------------- -------------------------------------------------------------------
@ -45,18 +53,19 @@ mc.py Monte Carlo energy relaxation wrapper on LAMMPS
gui.py GUI go/stop/temperature-slider to control LAMMPS gui.py GUI go/stop/temperature-slider to control LAMMPS
plot.py real-time temperature plot with GnuPlot via Pizza.py plot.py real-time temperature plot with GnuPlot via Pizza.py
matplotlib_plot.py real-time temperature plot with Matplotlib via Pizza.py matplotlib_plot.py real-time temperature plot with Matplotlib via Pizza.py
viz_tool.py real-time viz via some viz package viz_<tool>.py real-time viz via some viz package
vizplotgui_tool.py combination of viz.py and plot.py and gui.py vizplotgui_<tool>.py combination of viz.py and plot.py and gui.py
For the viz_tool.py and vizplotgui_tool.py commands, replace "tool" For the viz_<tool>.py and vizplotgui_<tool>.py commands, replace
with "gl" or "atomeye" or "pymol", depending on what visualization "<tool>" with "gl" or "atomeye" or "pymol", depending on what
package you have installed. We hope to add a VMD option soon. visualization package you have installed. We hope to add a VMD option
soon.
Note that for GL, you need to be able to run the Pizza.py GL tool, 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 Pizza.py doc which is included in the pizza sub-directory. See the Pizza.py doc
pages for more info: pages for more info:
http://www.sandia.gov/~sjplimp/pizza.html https://lammps.github.io/pizza/
Note that for AtomEye, you need version 3, and their is a line in the Note that for AtomEye, you need version 3, and their is a line in the
scripts that specifies the path and name of the executable. See scripts that specifies the path and name of the executable. See
@ -115,17 +124,14 @@ one-processor run, where both Python and LAMMPS will run on single
processors. Each running job will read the same input file, and write processors. Each running job will read the same input file, and write
to same log.lammps file, which isn't too useful. to same log.lammps file, which isn't too useful.
However, if you have the mpi4py Python package installed and uncomment mpi4py However, if you have the mpi4py Python package installed and uncomment
code in simple.py, then the above commands will invoke 1 instance of a mpi4py code in simple.py, then the above commands will invoke 1 instance
P-processor run. Both Python and LAMMPS will run on P processors. The job will of a P-processor run. Both Python and LAMMPS will run on P processors.
read the input file and write a single log.lammps file. The job will read the input file and write a single log.lammps file.
The split.py script can also be run in parallel. It uses mpi4py
version 2.0.0 (or later), which makes it possible to pass a
communicator when creating the LAMMPS object and thus run multiple
instances of LAMMPS at the same time, each on a different subset of
MPI ranks. Or run LAMMPS on one subset and some other program on the
rest of the MPI ranks, concurrently. See comments in the split.py
script for more details.
The split.py script can also be run in parallel. It uses mpi4py version
2.0.0 (or later), which makes it possible to pass a communicator when
creating the LAMMPS object and thus run multiple instances of LAMMPS at
the same time, each on a different subset of MPI ranks. Or run LAMMPS
on one subset and some other program on the rest of the MPI ranks,
concurrently. See comments in the split.py script for more details.

View File

@ -23,6 +23,9 @@ def get_version_number():
if __file__.find(join('python', 'lammps', '__init__.py')) > 0: if __file__.find(join('python', 'lammps', '__init__.py')) > 0:
return 0 return 0
if version_info.major < 3 or (version_info.major == 3 and version_info.minor < 6):
raise SystemError('LAMMPS only supports Python version 3.6 or later')
vstring = None vstring = None
if version_info.major == 3 and version_info.minor >= 8: if version_info.major == 3 and version_info.minor >= 8:
from importlib.metadata import version, PackageNotFoundError from importlib.metadata import version, PackageNotFoundError

View File

@ -83,8 +83,6 @@ class command_wrapper(object):
def _wrap_args(self, x): def _wrap_args(self, x):
if callable(x): if callable(x):
if sys.version_info < (3,):
raise Exception("Passing functions or lambdas directly as arguments is only supported in Python 3 or newer")
import hashlib import hashlib
import __main__ import __main__
sha = hashlib.sha256() sha = hashlib.sha256()
@ -105,11 +103,6 @@ class command_wrapper(object):
all the arguments, concatinates them to a single string, and executes it using all the arguments, concatinates them to a single string, and executes it using
:py:meth:`lammps.command`. :py:meth:`lammps.command`.
Starting with Python 3.6 it also supports keyword arguments. key=value is
transformed into 'key value'. Note, since these have come last in the
parameter list, only a subset of LAMMPS commands can be used with this
syntax.
LAMMPS commands that accept callback functions (such as fix python/invoke) LAMMPS commands that accept callback functions (such as fix python/invoke)
can be passed functions and lambdas directly. The first argument of such can be passed functions and lambdas directly. The first argument of such
callbacks will be an lammps object constructed from the passed LAMMPS callbacks will be an lammps object constructed from the passed LAMMPS
@ -121,9 +114,6 @@ class command_wrapper(object):
def handler(*args, **kwargs): def handler(*args, **kwargs):
cmd_args = [name] + [str(self._wrap_args(x)) for x in args] cmd_args = [name] + [str(self._wrap_args(x)) for x in args]
if len(kwargs) > 0 and sys.version_info < (3,6):
raise Exception("Keyword arguments are only supported in Python 3.6 or newer")
# Python 3.6+ maintains ordering of kwarg keys # Python 3.6+ maintains ordering of kwarg keys
for k in kwargs.keys(): for k in kwargs.keys():
cmd_args.append(k) cmd_args.append(k)
@ -530,16 +520,10 @@ class lammps(object):
else: else:
# magic to convert ptr to ctypes ptr # magic to convert ptr to ctypes ptr
if sys.version_info >= (3, 0):
# Python 3 (uses PyCapsule API) # Python 3 (uses PyCapsule API)
pythonapi.PyCapsule_GetPointer.restype = c_void_p pythonapi.PyCapsule_GetPointer.restype = c_void_p
pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p] pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p]
self.lmp = c_void_p(pythonapi.PyCapsule_GetPointer(ptr, None)) self.lmp = c_void_p(pythonapi.PyCapsule_GetPointer(ptr, None))
else:
# Python 2 (uses PyCObject API)
pythonapi.PyCObject_AsVoidPtr.restype = c_void_p
pythonapi.PyCObject_AsVoidPtr.argtypes = [py_object]
self.lmp = c_void_p(pythonapi.PyCObject_AsVoidPtr(ptr))
# check if library initilialization failed # check if library initilialization failed
if not self.lmp: if not self.lmp:

View File

@ -68,12 +68,12 @@ MLIAPModelPythonKokkos<DeviceType>::MLIAPModelPythonKokkos(LAMMPS *lmp, char *co
// Recipe from lammps/src/pair_python.cpp : // Recipe from lammps/src/pair_python.cpp :
// add current directory to PYTHONPATH // add current directory to PYTHONPATH
PyObject *py_path = PySys_GetObject((char *) "path"); PyObject *py_path = PySys_GetObject((char *) "path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well
const char *potentials_path = getenv("LAMMPS_POTENTIALS"); const char *potentials_path = getenv("LAMMPS_POTENTIALS");
if (potentials_path != nullptr) { if (potentials_path != nullptr) {
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); PyList_Append(py_path, PyUnicode_FromString(potentials_path));
} }
PyGILState_Release(gstate); PyGILState_Release(gstate);
if (coefffilename) read_coeffs(coefffilename); if (coefffilename) read_coeffs(coefffilename);

View File

@ -62,12 +62,12 @@ MLIAPModelPython::MLIAPModelPython(LAMMPS *lmp, char *coefffilename, bool is_chi
// Recipe from lammps/src/pair_python.cpp : // Recipe from lammps/src/pair_python.cpp :
// add current directory to PYTHONPATH // add current directory to PYTHONPATH
PyObject *py_path = PySys_GetObject((char *) "path"); PyObject *py_path = PySys_GetObject((char *) "path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well // if LAMMPS_POTENTIALS environment variable is set, add it to PYTHONPATH as well
const char *potentials_path = getenv("LAMMPS_POTENTIALS"); const char *potentials_path = getenv("LAMMPS_POTENTIALS");
if (potentials_path != nullptr) { if (potentials_path != nullptr) {
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); PyList_Append(py_path, PyUnicode_FromString(potentials_path));
} }
PyGILState_Release(gstate); PyGILState_Release(gstate);
if (coefffilename) read_coeffs(coefffilename); if (coefffilename) read_coeffs(coefffilename);

View File

@ -2,6 +2,12 @@
SHELL = /bin/bash SHELL = /bin/bash
PYTHON = python PYTHON = python
PYTHON_VERSION=$(word 2,$(shell $(PYTHON) -V 2>&1 | tr '.' ' '))
ifeq ($(PYTHON_VERSION),2)
PYTHON_CHECK=@echo LAMMPS requires Python 3. Try: 'make PYTHON=python3 ...' ; exit 1
else
PYTHON_CHECK=@echo
endif
DYN_LIB = -ldl DYN_LIB = -ldl
#.IGNORE: #.IGNORE:
@ -276,7 +282,7 @@ LIBDIR = $(@:lib-%=%)
# List of all targets # List of all targets
help: help:
@echo '' $(PYTHON_CHECK)
@echo 'make clean-all delete all object files' @echo 'make clean-all delete all object files'
@echo 'make clean-machine delete object files for one machine' @echo 'make clean-machine delete object files for one machine'
@echo 'make mpi-stubs build dummy MPI library in STUBS' @echo 'make mpi-stubs build dummy MPI library in STUBS'
@ -378,6 +384,7 @@ gitversion:
# shared = shared compile in Obj_shared_machine # shared = shared compile in Obj_shared_machine
.DEFAULT: .DEFAULT:
$(PYTHON_CHECK)
@if [ $@ = "serial" ]; \ @if [ $@ = "serial" ]; \
then cd STUBS; $(MAKE); cd ..; fi then cd STUBS; $(MAKE); cd ..; fi
@test -f MAKE/Makefile.$@ -o -f MAKE/OPTIONS/Makefile.$@ -o \ @test -f MAKE/Makefile.$@ -o -f MAKE/OPTIONS/Makefile.$@ -o \
@ -465,6 +472,7 @@ mpi-stubs:
sinclude ../lib/python/Makefile.lammps sinclude ../lib/python/Makefile.lammps
install-python: install-python:
$(PYTHON_CHECK)
@rm -rf ../python/build @rm -rf ../python/build
@$(PYTHON) ../python/install.py -p ../python/lammps -l ../src/liblammps.so -w $(PWD) -v $(PWD)/version.h @$(PYTHON) ../python/install.py -p ../python/lammps -l ../src/liblammps.so -w $(PWD) -v $(PWD)/version.h
@ -483,49 +491,59 @@ tar:
check: check-whitespace check-permissions check-homepage check-errordocs check-fmtlib check-docs check-version check: check-whitespace check-permissions check-homepage check-errordocs check-fmtlib check-docs check-version
check-whitespace: check-whitespace:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/whitespace.py .. $(PYTHON) ../tools/coding_standard/whitespace.py ..
fix-whitespace: fix-whitespace:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/whitespace.py .. -f $(PYTHON) ../tools/coding_standard/whitespace.py .. -f
check-permissions: check-permissions:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/permissions.py .. $(PYTHON) ../tools/coding_standard/permissions.py ..
fix-permissions: fix-permissions:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/permissions.py .. -f $(PYTHON) ../tools/coding_standard/permissions.py .. -f
check-homepage: check-homepage:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/homepage.py .. $(PYTHON) ../tools/coding_standard/homepage.py ..
fix-homepage: fix-homepage:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/homepage.py .. -f $(PYTHON) ../tools/coding_standard/homepage.py .. -f
check-errordocs: check-errordocs:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/errordocs.py .. $(PYTHON) ../tools/coding_standard/errordocs.py ..
fix-errordocs: fix-errordocs:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/errordocs.py .. -f $(PYTHON) ../tools/coding_standard/errordocs.py .. -f
check-fmtlib: check-fmtlib:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/fmtlib.py .. $(PYTHON) ../tools/coding_standard/fmtlib.py ..
fix-fmtlib: fix-fmtlib:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/fmtlib.py .. -f $(PYTHON) ../tools/coding_standard/fmtlib.py .. -f
check-docs: check-docs:
$(PYTHON_CHECK)
$(MAKE) $(MFLAGS) -C ../doc anchor_check style_check package_check role_check $(MAKE) $(MFLAGS) -C ../doc anchor_check style_check package_check role_check
check-version: check-version:
$(PYTHON_CHECK)
$(PYTHON) ../tools/coding_standard/versiontags.py .. || echo $(PYTHON) ../tools/coding_standard/versiontags.py .. || echo
format-src: format-src:
clang-format -i --verbose --style=file *.cpp *.h */*.cpp */*.h clang-format -i --verbose --style=file *.cpp *.h */*.cpp */*.h
format-tests: format-tests:
clang-format -i --verbose --style=file ../unittest/*/*.cpp ../unittest/*/*.h clang-format -i --verbose --style=file ../unittest/*/*.cpp ../unittest/*/*.h
# Package management # Package management
package: package:

View File

@ -70,7 +70,7 @@ FixPythonInvoke::FixPythonInvoke(LAMMPS *lmp, int narg, char **arg) :
error->all(FLERR,"Could not find Python function"); error->all(FLERR,"Could not find Python function");
} }
lmpPtr = PY_VOID_POINTER(lmp); lmpPtr = PyCapsule_New((void *)lmp, nullptr, nullptr);
// nvalid = next step on which end_of_step or post_force does something // nvalid = next step on which end_of_step or post_force does something
// add nextvalid() to all computes that store invocation times // add nextvalid() to all computes that store invocation times

View File

@ -44,7 +44,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) :
// add current directory to PYTHONPATH // add current directory to PYTHONPATH
PyObject *py_path = PySys_GetObject((char *)"path"); PyObject *py_path = PySys_GetObject((char *)"path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// create integrator instance // create integrator instance
@ -73,7 +73,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) :
error->all(FLERR,"Could not find integrator class {} in module {}", cls_name, module_name); error->all(FLERR,"Could not find integrator class {} in module {}", cls_name, module_name);
} }
PyObject *ptr = PY_VOID_POINTER(lmp); PyObject *ptr = PyCapsule_New((void *)lmp, nullptr, nullptr);
PyObject *py_move_obj = PyObject_CallFunction(py_move_type, (char *)"O", ptr); PyObject *py_move_obj = PyObject_CallFunction(py_move_type, (char *)"O", ptr);
Py_CLEAR(ptr); Py_CLEAR(ptr);

View File

@ -54,14 +54,14 @@ PairPython::PairPython(LAMMPS *lmp) : Pair(lmp) {
PyUtils::GIL lock; PyUtils::GIL lock;
PyObject *py_path = PySys_GetObject((char *)"path"); PyObject *py_path = PySys_GetObject((char *)"path");
PyList_Append(py_path, PY_STRING_FROM_STRING(".")); PyList_Append(py_path, PyUnicode_FromString("."));
// if LAMMPS_POTENTIALS environment variable is set, // if LAMMPS_POTENTIALS environment variable is set,
// add it to PYTHONPATH as well // add it to PYTHONPATH as well
const char *potentials_path = getenv("LAMMPS_POTENTIALS"); const char *potentials_path = getenv("LAMMPS_POTENTIALS");
if (potentials_path != nullptr) { if (potentials_path != nullptr) {
PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); PyList_Append(py_path, PyUnicode_FromString(potentials_path));
} }
} }

View File

@ -16,22 +16,11 @@
#include <Python.h> #include <Python.h>
// Wrap API changes between Python 2 and 3 using macros #if PY_VERSION_HEX < 0x030600f0
#if PY_MAJOR_VERSION == 2 #error Python version 3.6 or later is required by LAMMPS
#if defined(_MSC_VER) || defined(__MINGW32__)
#define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X)
#define PY_INT_AS_LONG(X) PyLong_AsLongLong(X)
#define PY_LONG_FROM_STRING(X) std::stoll(X)
#else
#define PY_INT_FROM_LONG(X) PyInt_FromLong(X)
#define PY_INT_AS_LONG(X) PyInt_AsLong(X)
#define PY_LONG_FROM_STRING(X) std::stol(X)
#endif #endif
#define PY_STRING_FROM_STRING(X) PyString_FromString(X)
#define PY_VOID_POINTER(X) PyCObject_FromVoidPtr((void *) X, nullptr)
#define PY_STRING_AS_STRING(X) PyString_AsString(X)
#elif PY_MAJOR_VERSION == 3 // Wrap API differences between platforms using macros
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X) #define PY_INT_FROM_LONG(X) PyLong_FromLongLong(X)
#define PY_INT_AS_LONG(X) PyLong_AsLongLong(X) #define PY_INT_AS_LONG(X) PyLong_AsLongLong(X)
@ -41,9 +30,5 @@
#define PY_INT_AS_LONG(X) PyLong_AsLong(X) #define PY_INT_AS_LONG(X) PyLong_AsLong(X)
#define PY_LONG_FROM_STRING(X) std::stol(X) #define PY_LONG_FROM_STRING(X) std::stol(X)
#endif #endif
#define PY_STRING_FROM_STRING(X) PyUnicode_FromString(X)
#define PY_VOID_POINTER(X) PyCapsule_New((void *) X, nullptr, nullptr)
#define PY_STRING_AS_STRING(X) PyUnicode_AsUTF8(X)
#endif
#endif #endif

View File

@ -361,12 +361,12 @@ void PythonImpl::invoke_function(int ifunc, char *result)
if (!str) if (!str)
error->all(FLERR, "Could not evaluate Python function {} input variable: {}", error->all(FLERR, "Could not evaluate Python function {} input variable: {}",
pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]); pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]);
pValue = PY_STRING_FROM_STRING(str); pValue = PyUnicode_FromString(str);
} else { } else {
pValue = PY_STRING_FROM_STRING(pfuncs[ifunc].svalue[i]); pValue = PyUnicode_FromString(pfuncs[ifunc].svalue[i]);
} }
} else if (itype == PTR) { } else if (itype == PTR) {
pValue = PY_VOID_POINTER(lmp); pValue = PyCapsule_New((void *)lmp, nullptr, nullptr);
} else { } else {
error->all(FLERR, "Unsupported variable type: {}", itype); error->all(FLERR, "Unsupported variable type: {}", itype);
} }
@ -397,7 +397,7 @@ void PythonImpl::invoke_function(int ifunc, char *result)
auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue)); auto value = fmt::format("{:.15g}", PyFloat_AsDouble(pValue));
strncpy(result, value.c_str(), Variable::VALUELENGTH - 1); strncpy(result, value.c_str(), Variable::VALUELENGTH - 1);
} else if (otype == STRING) { } else if (otype == STRING) {
const char *pystr = PY_STRING_AS_STRING(pValue); const char *pystr = PyUnicode_AsUTF8(pValue);
if (pfuncs[ifunc].longstr) if (pfuncs[ifunc].longstr)
strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr); strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr);
else else

View File

@ -17,6 +17,7 @@
// collection of smart pointers for specific purposes // collection of smart pointers for specific purposes
#include <cstdio> #include <cstdio>
#include <utility>
namespace LAMMPS_NS { namespace LAMMPS_NS {
@ -36,7 +37,7 @@ class SafeFilePtr {
SafeFilePtr(FILE *_fp) : fp(_fp) {}; SafeFilePtr(FILE *_fp) : fp(_fp) {};
SafeFilePtr(const SafeFilePtr &) = delete; SafeFilePtr(const SafeFilePtr &) = delete;
SafeFilePtr(const SafeFilePtr &&) = delete; SafeFilePtr(SafeFilePtr &&o) noexcept : fp(std::exchange(o.fp, nullptr)) {}
SafeFilePtr &operator=(const SafeFilePtr &) = delete; SafeFilePtr &operator=(const SafeFilePtr &) = delete;
~SafeFilePtr() ~SafeFilePtr()