diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 591958f996..c1a0875c15 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -225,6 +225,12 @@ if(DEFINED ENV{VIRTUAL_ENV} AND NOT Python_EXECUTABLE) " Setting Python interpreter to: ${Python_EXECUTABLE}") 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") mark_as_advanced(LAMMPS_MACHINE) if(LAMMPS_MACHINE) diff --git a/cmake/Modules/CodingStandard.cmake b/cmake/Modules/CodingStandard.cmake index 94639c7771..4e99c2e39c 100644 --- a/cmake/Modules/CodingStandard.cmake +++ b/cmake/Modules/CodingStandard.cmake @@ -1,40 +1,39 @@ -# use default (or custom) Python executable, if version is sufficient -if(Python_VERSION VERSION_GREATER_EQUAL 3.6) +# use default (or custom) Python executable. +# Python version check is in main CMakeLists.txt file +if(Python_EXECUTABLE) set(Python3_EXECUTABLE ${Python_EXECUTABLE}) endif() find_package(Python3 COMPONENTS Interpreter) if(Python3_EXECUTABLE) - if(Python3_VERSION VERSION_GREATER_EQUAL 3.6) - add_custom_target( - check-whitespace - ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py . - WORKING_DIRECTORY ${LAMMPS_DIR} - COMMENT "Check for whitespace errors") - add_custom_target( - check-homepage - ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/homepage.py . - WORKING_DIRECTORY ${LAMMPS_DIR} - COMMENT "Check for homepage URL errors") - add_custom_target( - check-permissions - ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py . - WORKING_DIRECTORY ${LAMMPS_DIR} - COMMENT "Check for permission errors") - add_custom_target( - fix-whitespace - ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py -f . - WORKING_DIRECTORY ${LAMMPS_DIR} - COMMENT "Fix whitespace errors") - add_custom_target( - fix-homepage - ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/homepage.py -f . - WORKING_DIRECTORY ${LAMMPS_DIR} - COMMENT "Fix homepage URL errors") - add_custom_target( - fix-permissions - ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f . - WORKING_DIRECTORY ${LAMMPS_DIR} - COMMENT "Fix permission errors") - endif() + add_custom_target( + check-whitespace + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Check for whitespace errors") + add_custom_target( + check-homepage + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/homepage.py . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Check for homepage URL errors") + add_custom_target( + check-permissions + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Check for permission errors") + add_custom_target( + fix-whitespace + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/whitespace.py -f . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Fix whitespace errors") + add_custom_target( + fix-homepage + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/homepage.py -f . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Fix homepage URL errors") + add_custom_target( + fix-permissions + ${Python3_EXECUTABLE} ${LAMMPS_TOOLS_DIR}/coding_standard/permissions.py -f . + WORKING_DIRECTORY ${LAMMPS_DIR} + COMMENT "Fix permission errors") endif() diff --git a/cmake/Modules/Packages/ML-IAP.cmake b/cmake/Modules/Packages/ML-IAP.cmake index 91b772efb5..1691af8d95 100644 --- a/cmake/Modules/Packages/ML-IAP.cmake +++ b/cmake/Modules/Packages/ML-IAP.cmake @@ -24,9 +24,7 @@ if(MLIAP_ENABLE_PYTHON) if(NOT PKG_PYTHON) message(FATAL_ERROR "Must enable PYTHON package for including Python support in ML-IAP") endif() - if(Python_VERSION VERSION_LESS 3.6) - message(FATAL_ERROR "Python support in ML-IAP requires Python 3.6 or later") - endif() + # Python version check is in main CMakeLists.txt file set(MLIAP_BINARY_DIR ${CMAKE_BINARY_DIR}/cython) file(GLOB MLIAP_CYTHON_SRC CONFIGURE_DEPENDS ${LAMMPS_SOURCE_DIR}/ML-IAP/*.pyx) diff --git a/doc/src/Build_extras.rst b/doc/src/Build_extras.rst index dab2267ee8..f57407f9c1 100644 --- a/doc/src/Build_extras.rst +++ b/doc/src/Build_extras.rst @@ -1139,11 +1139,10 @@ POEMS package PYTHON package --------------------------- -Building with the PYTHON package requires you have a the Python development -headers and library available on your system, which needs to be a Python 2.7 -version or a Python 3.x version. Since support for Python 2.x has ended, -using Python 3.x is strongly recommended. See ``lib/python/README`` for -additional details. +Building with the PYTHON package requires you have a the Python +development headers and library available on your system, which +needs to be Python version 3.6 or later. See ``lib/python/README`` +for additional details. .. tabs:: @@ -1159,7 +1158,7 @@ additional details. set the Python_EXECUTABLE variable to specify which Python interpreter should be used. Note note that you will also need to have the development headers installed for this version, - e.g. python2-devel. + e.g. python3-devel. .. tab:: Traditional make diff --git a/doc/src/Build_make.rst b/doc/src/Build_make.rst index 00f2f0b24d..477c1c6e34 100644 --- a/doc/src/Build_make.rst +++ b/doc/src/Build_make.rst @@ -30,9 +30,9 @@ additional tools to be available and functioning. * 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`` * Python (optional, required for ``make lib-`` in the ``src`` - folder). Python scripts are currently tested with python 2.7 and - 3.6 to 3.11. The procedure for :doc:`building the documentation - ` *requires* Python 3.5 or later. + folder). Python scripts are currently tested with 3.6 to 3.11. + The procedure for :doc:`building the documentation ` + *requires* Python 3.8 or later. Getting started ^^^^^^^^^^^^^^^ diff --git a/doc/src/Build_manual.rst b/doc/src/Build_manual.rst index 490594af02..7a969877a1 100644 --- a/doc/src/Build_manual.rst +++ b/doc/src/Build_manual.rst @@ -162,7 +162,7 @@ are usually installed by default, the following packages are required: - dvipng - ellipse - fncychap - - fontawesom + - fontawesome - framed - geometry - gyre diff --git a/doc/src/Intro_portability.rst b/doc/src/Intro_portability.rst index 036529ff9d..8bb716833f 100644 --- a/doc/src/Intro_portability.rst +++ b/doc/src/Intro_portability.rst @@ -13,10 +13,14 @@ Programming language standards Most of the C++ code currently requires a compiler compatible with the 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 -Python 2.7. Some Python scripts *require* Python 3 and a few others -still need to be ported from Python 2 to Python 3. +the Python code is written to be compatible with Python 3.6 or later. +.. 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 ^^^^^^^^^^^^^ @@ -24,8 +28,8 @@ Build systems LAMMPS can be compiled from source code using a (traditional) build system based on shell scripts, a few shell utilities (grep, sed, cat, tr) and the GNU make program. This requires running within a Bourne -shell (``/bin/sh``). Alternatively, a build system with different back ends -can be created using CMake. CMake must be at least version 3.16. +shell (``/bin/sh``). Alternatively, a build system with different back +ends can be created using CMake. CMake must be at least version 3.16. Operating systems ^^^^^^^^^^^^^^^^^ diff --git a/doc/src/Modify_requirements.rst b/doc/src/Modify_requirements.rst index c3e514a423..850fbf95c1 100644 --- a/doc/src/Modify_requirements.rst +++ b/doc/src/Modify_requirements.rst @@ -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 C++ code. -Python code must be compatible with Python 3.5 and later. Large parts -of LAMMPS (including the :ref:`PYTHON package `) are also -compatible with Python 2.7. Compatibility with Python 2.7 is desirable, -but compatibility with Python 3.5 is **required**. +Python code currently must be compatible with Python 3.6. If a later +version or Python is required, it needs to be documented. Compatibility with older programming language standards is very important to maintain portability and availability of LAMMPS on many diff --git a/doc/src/Packages_details.rst b/doc/src/Packages_details.rst index baefee0185..870dc8fbf7 100644 --- a/doc/src/Packages_details.rst +++ b/doc/src/Packages_details.rst @@ -2428,7 +2428,7 @@ ways to use LAMMPS and Python together. Building with the PYTHON package assumes you have a Python development 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:** diff --git a/doc/src/Python_install.rst b/doc/src/Python_install.rst index 01610b84f0..1e53a99914 100644 --- a/doc/src/Python_install.rst +++ b/doc/src/Python_install.rst @@ -7,6 +7,10 @@ LAMMPS shared library through the Python `ctypes `_ module. Because of the dynamic loading, it is required that LAMMPS is compiled in :ref:`"shared" mode `. +.. 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: * 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 python3 -m venv $HOME/myenv - For Python versions prior 3.3 you can use `virtualenv - `_ - command instead of "python3 -m venv". This step has to be done - only once. - To activate the virtual environment type: .. 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 `_ (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: - Via ``pip`` into a local user folder with: .. code-block:: bash - pip install --user mpi4py + python3 -m pip install --user mpi4py - Via ``dnf`` into a system folder for RedHat/Fedora systems: @@ -261,20 +260,20 @@ follows: # for use with OpenMPI sudo dnf install python3-mpi4py-openmpi # for use with MPICH - sudo dnf install python3-mpi4py-openmpi + sudo dnf install python3-mpi4py-mpich - Via ``pip`` into a virtual environment (see above): .. code-block:: console $ source $HOME/myenv/activate - (myenv)$ pip install mpi4py + (myenv)$ python -m pip install mpi4py - Via ``pip`` into a system folder (not recommended): .. code-block:: bash - sudo pip install mpi4py + sudo python3 -m pip install mpi4py For more detailed installation instructions and additional options, please see the `mpi4py installation `_ page. diff --git a/doc/src/Python_overview.rst b/doc/src/Python_overview.rst index 85bc0d3bfa..57b9ee6145 100644 --- a/doc/src/Python_overview.rst +++ b/doc/src/Python_overview.rst @@ -44,15 +44,11 @@ Below is an example output for Python version 3.8.5. .. warning:: The options described in this section of the manual for using Python - with LAMMPS currently support either Python 2 or 3. Specifically - version 2.7 or later and 3.6 or later. Since the Python community no - longer maintains Python 2 (see `this notice - `_), we recommend use of - Python 3 with LAMMPS. While Python 2 code should continue to work, - 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 `_ + with LAMMPS support only Python 3.6 or later. For use with Python + 2.x you will need to use an older LAMMPS version like 29 Aug 2024 + or older. 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 `_ --------- diff --git a/doc/src/region2vmd.rst b/doc/src/region2vmd.rst index 6cea199760..54216bb925 100644 --- a/doc/src/region2vmd.rst +++ b/doc/src/region2vmd.rst @@ -166,11 +166,7 @@ Only the following region styles are currently supported: *block*, *cone*, *cylinder*, *ellipsoid*, *prism*, and *sphere*. Regions formed from unions or intersections of other regions are not supported. -For region style *cone* one of the two radii must be zero, since the -equivalent VMD graphics primitive does not support truncated cones. -Also the VMD graphics primitive does not support open cones. - -Rotating regions are not supported. +Rotating regions are currently not supported. Related commands """""""""""""""" diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index 730c6dd53f..f94d528cfe 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -99,6 +99,7 @@ AMD amino Amirjalayer Amit +amsmath amu Amzallag analytical @@ -128,6 +129,7 @@ Antisymmetrized antisymmetry anton Antonelli +anysize api apolar Apoorva @@ -613,6 +615,7 @@ Courant covalent covalently covariance +cp cpp cpu cradius @@ -905,6 +908,7 @@ dUs Duval dV dvector +dvipng dVx dW dx @@ -1215,12 +1219,14 @@ fmz fN Fn fname +fncychap fno Fnudge foces Fock Fogarty Foiles +fontawesome fopenmp forceclear forestgreen @@ -1407,6 +1413,7 @@ Gunsteren Gunzenmuller Guo gw +gyre gyromagnetic gz gzip @@ -1532,10 +1539,12 @@ hydrostatically hydroxyl Hynninen Hyoungki +hypcap hyperdynamics hyperparameters hyperplane hyperradius +hyperref hyperspherical hysteretic hz @@ -2514,6 +2523,7 @@ Ndof Ndouble ndx neb +needspace neel Neel Neelov @@ -2918,6 +2928,7 @@ picogram picograms picosecond picoseconds +pict pid piecewise Pieniazek @@ -3689,6 +3700,7 @@ Sz Tabbernor tabinner tabstyle +tabulary Tadmor Tafipolsky tagID @@ -3786,6 +3798,7 @@ timestamps timestep timestepping timesteps +titlesec TiN TiO Tirado @@ -3962,6 +3975,7 @@ untilted Unwin uparrow upenn +upquote upto Urbakh Urbana @@ -4148,6 +4162,7 @@ Workum Worley wormlike wpbe +wrapfig Wriggers writedata Wuppertal @@ -4178,6 +4193,7 @@ Xia Xiaohu Xiaowang Xie +xindy xk xlat xlattice diff --git a/lib/python/Makefile.lammps.python2 b/lib/python/Makefile.lammps.python2 deleted file mode 100644 index 7b54b4c3df..0000000000 --- a/lib/python/Makefile.lammps.python2 +++ /dev/null @@ -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) diff --git a/lib/python/Makefile.lammps.python2.7 b/lib/python/Makefile.lammps.python3.13 similarity index 100% rename from lib/python/Makefile.lammps.python2.7 rename to lib/python/Makefile.lammps.python3.13 diff --git a/lib/python/README b/lib/python/README index 8de2bc4bd7..c84b291f05 100644 --- a/lib/python/README +++ b/lib/python/README @@ -9,30 +9,29 @@ installation. If needed, you can copy one of the other provided Makefile.lammps.* files to to Makefile.lammps before building LAMMPS itself. -The files Makefile.lammps.python2 and Makefile.lammps.python3 are -similar to the default file, but meant for the case that both, -python 2 and python 3, are installed simultaneously and you want -to prefer one over the other. If neither of these files work, you -may have to create a custom Makefile.lammps file suitable for -the version of Python on your system. To illustrate, these are -example settings from the Makefile.lammps.python2.7 file: +The file Makefile.lammps.python3 is similar to the default file, but +meant for the case that both, python 2 and python 3, are installed +simultaneously. LAMMPS only supports python 3. If neither of these +files work, you may have to create a custom Makefile.lammps file +suitable for the version of Python on your system. To illustrate, these +are example settings from the Makefile.lammps.python3.13 file: -python_SYSINC = -I/usr/local/include/python2.7 -python_SYSLIB = -lpython2.7 -lnsl -ldl -lreadline -ltermcap -lpthread -lutil -lm -python_SYSPATH = -PYTHON=python2.7 +python_SYSINC = -I/usr/local/include/python3.13 +python_SYSLIB = -lpython3.13 -ldl -lm +python_SYSPATH = -L/usr/lib64 +PYTHON=python3.13 python_SYSINC refers to the directory where Python's Python.h file is found. LAMMPS includes this file. python_SYSLIB refers to the libraries needed to link to from an 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. 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 -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 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: -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 compiler (and linker) in order to embed the Python interpreter into diff --git a/python/README b/python/README index 0757a84cd6..97f47b2a36 100644 --- a/python/README +++ b/python/README @@ -1,20 +1,27 @@ -This directory contains Python code which wraps LAMMPS as a library -and allows the LAMMPS library interface to be invoked from Python, -either from a Python script or using Python interactively. +This directory contains the LAMMPS Python module that allows the LAMMPS +C library interface to be invoked from Python, either from a Python +script or using Python interactively. Details on the Python interface to LAMMPS and how to build LAMMPS as a 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 install-python # install into site-packages folder 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 -script directly to give you more control over where the two relevant -files are installed. See doc/Python_install.html for details. +variables in your shell environment. Or you can run the +python/install.py script directly to give you more control over where +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 of LAMMPS: @@ -24,39 +31,41 @@ of LAMMPS: >>> lmp = lammps() 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 -to run LAMMPS both in serial or parallel thru Python. +Python. See https://docs.lammps.org/Python_launch.html for examples how +to run LAMMPS both in serial or parallel from Python. 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 -for details. The Python code you invoke can also call back to LAMMPS -using the same interface described here for wrapping LAMMPS. +script, using the "python" command. See the +https://docs.lammps.org/python.html doc page for details. The Python +code you invoke can also call back to LAMMPS using the same interface +described here for wrapping LAMMPS. ------------------------------------------------------------------- Once you have successfully wrapped LAMMPS, you can run the Python scripts in the examples sub-directory: -trivial.py read/run a LAMMPS input script thru Python -demo.py invoke various LAMMPS library interface routines -simple.py parallel example, mimicing examples/COUPLE/simple/simple.cpp -split.py parallel example -mc.py Monte Carlo energy relaxation wrapper on LAMMPS -gui.py GUI go/stop/temperature-slider to control LAMMPS -plot.py real-time temperature plot with GnuPlot 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 -vizplotgui_tool.py combination of viz.py and plot.py and gui.py +trivial.py read/run a LAMMPS input script thru Python +demo.py invoke various LAMMPS library interface routines +simple.py parallel example, mimicing examples/COUPLE/simple/simple.cpp +split.py parallel example +mc.py Monte Carlo energy relaxation wrapper on LAMMPS +gui.py GUI go/stop/temperature-slider to control LAMMPS +plot.py real-time temperature plot with GnuPlot via Pizza.py +matplotlib_plot.py real-time temperature plot with Matplotlib via Pizza.py +viz_.py real-time viz via some viz package +vizplotgui_.py combination of viz.py and plot.py and gui.py -For the viz_tool.py and vizplotgui_tool.py commands, replace "tool" -with "gl" or "atomeye" or "pymol", depending on what visualization -package you have installed. We hope to add a VMD option soon. +For the viz_.py and vizplotgui_.py commands, replace +"" with "gl" or "atomeye" or "pymol", depending on what +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, which is included in the pizza sub-directory. See the Pizza.py doc 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 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 to same log.lammps file, which isn't too useful. -However, if you have the mpi4py Python package installed and uncomment mpi4py -code in simple.py, then the above commands will invoke 1 instance of a -P-processor run. Both Python and LAMMPS will run on P processors. 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. - +However, if you have the mpi4py Python package installed and uncomment +mpi4py code in simple.py, then the above commands will invoke 1 instance +of a P-processor run. Both Python and LAMMPS will run on P processors. +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. diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index fc35e45225..0cc658371f 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -23,6 +23,9 @@ def get_version_number(): if __file__.find(join('python', 'lammps', '__init__.py')) > 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 if version_info.major == 3 and version_info.minor >= 8: from importlib.metadata import version, PackageNotFoundError diff --git a/python/lammps/core.py b/python/lammps/core.py index 43d142c7de..d8fc3a666e 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -83,8 +83,6 @@ class command_wrapper(object): def _wrap_args(self, 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 __main__ sha = hashlib.sha256() @@ -105,11 +103,6 @@ class command_wrapper(object): all the arguments, concatinates them to a single string, and executes it using :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) can be passed functions and lambdas directly. The first argument of such callbacks will be an lammps object constructed from the passed LAMMPS @@ -121,9 +114,6 @@ class command_wrapper(object): def handler(*args, **kwargs): 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 for k in kwargs.keys(): cmd_args.append(k) @@ -530,16 +520,10 @@ class lammps(object): else: # magic to convert ptr to ctypes ptr - if sys.version_info >= (3, 0): - # Python 3 (uses PyCapsule API) - pythonapi.PyCapsule_GetPointer.restype = c_void_p - pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p] - 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)) + # Python 3 (uses PyCapsule API) + pythonapi.PyCapsule_GetPointer.restype = c_void_p + pythonapi.PyCapsule_GetPointer.argtypes = [py_object, c_char_p] + self.lmp = c_void_p(pythonapi.PyCapsule_GetPointer(ptr, None)) # check if library initilialization failed if not self.lmp: diff --git a/src/KOKKOS/mliap_model_python_kokkos.cpp b/src/KOKKOS/mliap_model_python_kokkos.cpp index 4435a0371a..1b010cc286 100644 --- a/src/KOKKOS/mliap_model_python_kokkos.cpp +++ b/src/KOKKOS/mliap_model_python_kokkos.cpp @@ -68,12 +68,12 @@ MLIAPModelPythonKokkos::MLIAPModelPythonKokkos(LAMMPS *lmp, char *co // Recipe from lammps/src/pair_python.cpp : // add current directory to PYTHONPATH 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 const char *potentials_path = getenv("LAMMPS_POTENTIALS"); 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); if (coefffilename) read_coeffs(coefffilename); diff --git a/src/ML-IAP/mliap_model_python.cpp b/src/ML-IAP/mliap_model_python.cpp index c06bbdc121..c1c534401a 100644 --- a/src/ML-IAP/mliap_model_python.cpp +++ b/src/ML-IAP/mliap_model_python.cpp @@ -62,12 +62,12 @@ MLIAPModelPython::MLIAPModelPython(LAMMPS *lmp, char *coefffilename, bool is_chi // Recipe from lammps/src/pair_python.cpp : // add current directory to PYTHONPATH 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 const char *potentials_path = getenv("LAMMPS_POTENTIALS"); 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); if (coefffilename) read_coeffs(coefffilename); diff --git a/src/Makefile b/src/Makefile index 3de8eb85d5..f4eafbf299 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,6 +2,12 @@ SHELL = /bin/bash 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 #.IGNORE: @@ -276,7 +282,7 @@ LIBDIR = $(@:lib-%=%) # List of all targets help: - @echo '' + $(PYTHON_CHECK) @echo 'make clean-all delete all object files' @echo 'make clean-machine delete object files for one machine' @echo 'make mpi-stubs build dummy MPI library in STUBS' @@ -378,6 +384,7 @@ gitversion: # shared = shared compile in Obj_shared_machine .DEFAULT: + $(PYTHON_CHECK) @if [ $@ = "serial" ]; \ then cd STUBS; $(MAKE); cd ..; fi @test -f MAKE/Makefile.$@ -o -f MAKE/OPTIONS/Makefile.$@ -o \ @@ -465,6 +472,7 @@ mpi-stubs: sinclude ../lib/python/Makefile.lammps install-python: + $(PYTHON_CHECK) @rm -rf ../python/build @$(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-whitespace: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/whitespace.py .. fix-whitespace: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/whitespace.py .. -f check-permissions: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/permissions.py .. fix-permissions: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/permissions.py .. -f check-homepage: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/homepage.py .. fix-homepage: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/homepage.py .. -f check-errordocs: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/errordocs.py .. fix-errordocs: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/errordocs.py .. -f check-fmtlib: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/fmtlib.py .. fix-fmtlib: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/fmtlib.py .. -f check-docs: + $(PYTHON_CHECK) $(MAKE) $(MFLAGS) -C ../doc anchor_check style_check package_check role_check check-version: + $(PYTHON_CHECK) $(PYTHON) ../tools/coding_standard/versiontags.py .. || echo - format-src: clang-format -i --verbose --style=file *.cpp *.h */*.cpp */*.h format-tests: clang-format -i --verbose --style=file ../unittest/*/*.cpp ../unittest/*/*.h - # Package management package: diff --git a/src/PYTHON/fix_python_invoke.cpp b/src/PYTHON/fix_python_invoke.cpp index 6f27831438..2485371690 100644 --- a/src/PYTHON/fix_python_invoke.cpp +++ b/src/PYTHON/fix_python_invoke.cpp @@ -70,7 +70,7 @@ FixPythonInvoke::FixPythonInvoke(LAMMPS *lmp, int narg, char **arg) : 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 // add nextvalid() to all computes that store invocation times diff --git a/src/PYTHON/fix_python_move.cpp b/src/PYTHON/fix_python_move.cpp index caa1557503..c0be31dee6 100644 --- a/src/PYTHON/fix_python_move.cpp +++ b/src/PYTHON/fix_python_move.cpp @@ -44,7 +44,7 @@ FixPythonMove::FixPythonMove(LAMMPS *lmp, int narg, char **arg) : // add current directory to PYTHONPATH PyObject *py_path = PySys_GetObject((char *)"path"); - PyList_Append(py_path, PY_STRING_FROM_STRING(".")); + PyList_Append(py_path, PyUnicode_FromString(".")); // 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); } - 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); Py_CLEAR(ptr); diff --git a/src/PYTHON/pair_python.cpp b/src/PYTHON/pair_python.cpp index 695954604c..0f7baa0104 100644 --- a/src/PYTHON/pair_python.cpp +++ b/src/PYTHON/pair_python.cpp @@ -54,14 +54,14 @@ PairPython::PairPython(LAMMPS *lmp) : Pair(lmp) { PyUtils::GIL lock; 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 const char *potentials_path = getenv("LAMMPS_POTENTIALS"); if (potentials_path != nullptr) { - PyList_Append(py_path, PY_STRING_FROM_STRING(potentials_path)); + PyList_Append(py_path, PyUnicode_FromString(potentials_path)); } } diff --git a/src/PYTHON/python_compat.h b/src/PYTHON/python_compat.h index d1194056d8..88c0969a59 100644 --- a/src/PYTHON/python_compat.h +++ b/src/PYTHON/python_compat.h @@ -16,22 +16,11 @@ #include -// Wrap API changes between Python 2 and 3 using macros -#if PY_MAJOR_VERSION == 2 -#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) +#if PY_VERSION_HEX < 0x030600f0 +#error Python version 3.6 or later is required by LAMMPS #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__) #define PY_INT_FROM_LONG(X) PyLong_FromLongLong(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_LONG_FROM_STRING(X) std::stol(X) #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 diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 91e0a7abe5..e4ec8d74d8 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -361,12 +361,12 @@ void PythonImpl::invoke_function(int ifunc, char *result) if (!str) error->all(FLERR, "Could not evaluate Python function {} input variable: {}", pfuncs[ifunc].name, pfuncs[ifunc].svalue[i]); - pValue = PY_STRING_FROM_STRING(str); + pValue = PyUnicode_FromString(str); } else { - pValue = PY_STRING_FROM_STRING(pfuncs[ifunc].svalue[i]); + pValue = PyUnicode_FromString(pfuncs[ifunc].svalue[i]); } } else if (itype == PTR) { - pValue = PY_VOID_POINTER(lmp); + pValue = PyCapsule_New((void *)lmp, nullptr, nullptr); } else { 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)); strncpy(result, value.c_str(), Variable::VALUELENGTH - 1); } else if (otype == STRING) { - const char *pystr = PY_STRING_AS_STRING(pValue); + const char *pystr = PyUnicode_AsUTF8(pValue); if (pfuncs[ifunc].longstr) strncpy(pfuncs[ifunc].longstr, pystr, pfuncs[ifunc].length_longstr); else diff --git a/src/safe_pointers.h b/src/safe_pointers.h index 22b2969ced..ffc13588c5 100644 --- a/src/safe_pointers.h +++ b/src/safe_pointers.h @@ -17,6 +17,7 @@ // collection of smart pointers for specific purposes #include +#include namespace LAMMPS_NS { @@ -36,7 +37,7 @@ class SafeFilePtr { SafeFilePtr(FILE *_fp) : fp(_fp) {}; SafeFilePtr(const SafeFilePtr &) = delete; - SafeFilePtr(const SafeFilePtr &&) = delete; + SafeFilePtr(SafeFilePtr &&o) noexcept : fp(std::exchange(o.fp, nullptr)) {} SafeFilePtr &operator=(const SafeFilePtr &) = delete; ~SafeFilePtr()