Merge branch 'develop' into collected-small-changes

This commit is contained in:
Axel Kohlmeyer
2022-02-27 19:33:04 -05:00
16 changed files with 207 additions and 158 deletions

1
.gitignore vendored
View File

@ -12,6 +12,7 @@
*.sif
*.dll
*.pyc
*.whl
a.out
__pycache__

View File

@ -16,6 +16,7 @@ endif()
project(lammps CXX)
set(SOVERSION 0)
get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
get_filename_component(LAMMPS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.. ABSOLUTE)
get_filename_component(LAMMPS_LIB_BINARY_DIR ${CMAKE_BINARY_DIR}/lib ABSOLUTE)
@ -748,13 +749,15 @@ if(BUILD_SHARED_LIBS)
else()
find_package(Python COMPONENTS Interpreter)
endif()
if(BUILD_IS_MULTI_CONFIG)
set(LIBLAMMPS_SHARED_BINARY ${CMAKE_BINARY_DIR}/$<CONFIG>/liblammps${LAMMPS_MACHINE}${CMAKE_SHARED_LIBRARY_SUFFIX})
else()
set(LIBLAMMPS_SHARED_BINARY ${CMAKE_BINARY_DIR}/liblammps${LAMMPS_MACHINE}${CMAKE_SHARED_LIBRARY_SUFFIX})
endif()
if(Python_EXECUTABLE)
add_custom_target(
install-python ${CMAKE_COMMAND} -E remove_directory build
COMMAND ${Python_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h
-p ${LAMMPS_PYTHON_DIR}/lammps
-l ${CMAKE_BINARY_DIR}/liblammps${LAMMPS_MACHINE}${CMAKE_SHARED_LIBRARY_SUFFIX}
WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR}
COMMAND ${Python_EXECUTABLE} ${LAMMPS_PYTHON_DIR}/install.py -p ${LAMMPS_PYTHON_DIR}/lammps -l ${LIBLAMMPS_SHARED_BINARY}
COMMENT "Installing LAMMPS Python module")
else()
add_custom_target(
@ -799,7 +802,6 @@ if(ClangFormat_FOUND)
endif()
get_target_property(DEFINES lammps COMPILE_DEFINITIONS)
get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(BUILD_IS_MULTI_CONFIG)
set(LAMMPS_BUILD_TYPE "Multi-Config")
else()

View File

@ -25,11 +25,10 @@ Installing the LAMMPS Python Module and Shared Library
======================================================
Making LAMMPS usable within Python and vice versa requires putting the
LAMMPS Python package (``lammps``) into a location where the
Python interpreter can find it and installing the LAMMPS shared library
into a folder that the dynamic loader searches or inside of the installed
``lammps`` package folder. There are multiple ways to achieve
this.
LAMMPS Python package (``lammps``) into a location where the Python
interpreter can find it and installing the LAMMPS shared library into a
folder that the dynamic loader searches or inside of the installed
``lammps`` package folder. There are multiple ways to achieve this.
#. Do a full LAMMPS installation of libraries, executables, selected
headers, documentation (if enabled), and supporting files (only
@ -159,38 +158,52 @@ this.
make install-python
This will try to install (only) the shared library and the Python
package into a system folder and if that fails (due to missing
write permissions) will instead do the installation to a user
folder under ``$HOME/.local``. For a system-wide installation you
This will try to build a so-called (binary) 'wheel', a compressed
binary python package and then install it with the python package
manager 'pip'. Installation will be attempted into a system-wide
``site-packages`` folder and if that fails into the corresponding
folder in the user's home directory. For a system-wide installation you
would have to gain superuser privilege, e.g. though ``sudo``
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+=================================================================+=============================================================+
| LAMMPS Python package | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``$HOME/.local/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``$HOME/.local/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
+------------------------+----------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+==========================================================+=============================================================+
| LAMMPS Python package | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+----------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``$HOME/.local/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+----------------------------------------------------------+-------------------------------------------------------------+
For a system-wide installation those folders would then become.
+------------------------+---------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+=========================================================+=============================================================+
| LAMMPS Python package | * ``/usr/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``/usr/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+---------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``/usr/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``/usr/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+---------------------------------------------------------+-------------------------------------------------------------+
+------------------------+-------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+=================================================+=============================================================+
| LAMMPS Python package | * ``/usr/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+-------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``/usr/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+-------------------------------------------------+-------------------------------------------------------------+
No environment variables need to be set for those, as those
folders are searched by default by Python or the LAMMPS Python
package.
.. versionchanged:: TBD
.. note::
If there is an existing installation of the LAMMPS python
module, ``make install-python`` will try to update it.
However, that will fail if the older version of the module
was installed by LAMMPS versions until 17Feb2022. Those
were using the distutils package, which does not create a
"manifest" that allows a clean uninstall. The ``make
install-python`` command will always produce a
lammps-<version>-<python>-<abi>-<os>-<arch>.whl file (the
'wheel'). And this file can be later installed directly with
``python -m pip install <wheel file>.whl`` without having to
type ``make install-python`` again and repeating the build
step, too.
For the traditional make process you can override the python
version to version x.y when calling ``make`` with
``PYTHON=pythonX.Y``. For a CMake based compilation this choice
@ -201,16 +214,12 @@ this.
.. code-block:: bash
$ python install.py -p <python package> -l <shared library> -v <version.h file> [-d <pydir>]
$ python install.py -p <python package> -l <shared library> [-n]
* The ``-p`` flag points to the ``lammps`` Python package folder to be installed,
* the ``-l`` flag points to the LAMMPS shared library file to be installed,
* the ``-v`` flag points to the ``version.h`` file in the LAMMPS source
* and the optional ``-d`` flag to a custom (legacy) installation folder
If you use a legacy installation folder, you will need to set your
``PYTHONPATH`` and ``LD_LIBRARY_PATH`` (and/or ``DYLD_LIBRARY_PATH``) environment
variables accordingly as explained in the description for "In place use".
* and the optional ``-n`` instructs the script to only build a wheel file
but not attempt to install it.
.. tab:: Virtual environment
@ -257,32 +266,29 @@ this.
package and the shared library file are installed into the
following locations:
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+=================================================================+=============================================================+
| LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+========================================================+=============================================================+
| LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
If you do a full installation (CMake only) with "install", this
leads to the following installation locations:
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+=================================================================+=============================================================+
| LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` (32bit) | ``X.Y`` depends on the installed Python version |
| | * ``$VIRTUAL_ENV/lib64/pythonX.Y/site-packages/lammps`` (64bit) | |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``$VIRTUAL_ENV/lib/`` (32bit) | Set shared loader environment variable to this path |
| | * ``$VIRTUAL_ENV/lib64/`` (64bit) | (see below for more info on this) |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS executable | * ``$VIRTUAL_ENV/bin/`` | |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS potential files | * ``$VIRTUAL_ENV/share/lammps/potentials/`` | Set ``LAMMPS_POTENTIALS`` environment variable to this path |
+------------------------+-----------------------------------------------------------------+-------------------------------------------------------------+
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
| File | Location | Notes |
+========================+========================================================+=============================================================+
| LAMMPS Python Module | * ``$VIRTUAL_ENV/lib/pythonX.Y/site-packages/lammps`` | ``X.Y`` depends on the installed Python version |
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS shared library | * ``$VIRTUAL_ENV/lib/`` (32bit) | Set shared loader environment variable to this path |
| | * ``$VIRTUAL_ENV/lib64/`` (64bit) | (see below for more info on this) |
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS executable | * ``$VIRTUAL_ENV/bin/`` | |
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
| LAMMPS potential files | * ``$VIRTUAL_ENV/share/lammps/potentials/`` | Set ``LAMMPS_POTENTIALS`` environment variable to this path |
+------------------------+--------------------------------------------------------+-------------------------------------------------------------+
In that case you need to modify the ``$HOME/myenv/bin/activate``
script in a similar fashion you need to update your

View File

@ -3,6 +3,7 @@ aat
abc
abf
ABI
abi
abo
Abramyan
absTol
@ -2450,6 +2451,7 @@ ortho
orthonormal
orthorhombic
Ortner
os
oso
Otype
Ouadfel
@ -3616,6 +3618,7 @@ wget
Whelan
whitesmoke
whitespace
whl
Wi
Wicaksono
widom

View File

@ -1,16 +1,17 @@
#!/usr/bin/env python
"""
Installer script to install the LAMMPS python package and the corresponding
shared library into either the system-wide site-packages tree, or - failing
that - into the corresponding user tree. Called from the 'install-python'
build target in the conventional and CMake based build systems
Script to build a "binary wheel" for the 'pip' Python package manager for
the LAMMPS python module which includes the shared library file. After a
successful build the script attempts to install the wheel into a system
specific site-packages folder or - failing that - into the corresponding
user site-packages folder. Called from the 'install-python' build target
in the GNU make and CMake based build systems. Can also be called
independently and used to build the wheel without installing it.
"""
# copy LAMMPS shared library and lammps package to system dirs
from __future__ import print_function
import sys,os,shutil,time
import sys,os,shutil,time,glob,subprocess
from argparse import ArgumentParser
parser = ArgumentParser(prog='install.py',
@ -20,11 +21,8 @@ parser.add_argument("-p", "--package", required=True,
help="path to the LAMMPS Python package")
parser.add_argument("-l", "--lib", required=True,
help="path to the compiled LAMMPS shared library")
parser.add_argument("-v", "--version", required=True,
help="path to the LAMMPS version.h header file")
parser.add_argument("-d","--dir",
help="Legacy custom installation folder selection for package and library")
parser.add_argument("-n", "--noinstall", action="store_true", default=False,
help="only build a binary wheel. Don't attempt to install it")
args = parser.parse_args()
@ -46,91 +44,70 @@ if args.lib:
else:
args.lib = os.path.abspath(args.lib)
if args.version:
if not os.path.exists(args.version):
print( "ERROR: LAMMPS version header file %s does not exist" % args.version)
parser.print_help()
sys.exit(1)
else:
args.version = os.path.abspath(args.version)
if args.dir:
if not os.path.isdir(args.dir):
print( "ERROR: Installation folder %s does not exist" % args.dir)
parser.print_help()
sys.exit(1)
else:
args.dir = os.path.abspath(args.dir)
# if a custom directory is given, we copy the files directly
# without any special processing or additional steps to that folder
if args.dir:
print("Copying LAMMPS Python package to custom folder %s" % args.dir)
try:
shutil.copytree(args.package, os.path.join(args.dir,'lammps'))
except shutil.Error:
pass # fail silently
print("Copying LAMMPS shared library to custom folder %s" % args.dir)
try:
shutil.copyfile(args.lib, os.path.join(args.dir,os.path.basename(args.lib)))
except shutil.Error:
pass # fail silently
sys.exit()
# extract LAMMPS version string from header
# and convert to python packaging compatible version
def get_lammps_version(header):
with open(header, 'r') as f:
line = f.readline()
start_pos = line.find('"')+1
end_pos = line.find('"', start_pos)
t = time.strptime("".join(line[start_pos:end_pos].split()), "%d%b%Y")
return "{}.{}.{}".format(t.tm_year,t.tm_mon,t.tm_mday)
verstr = get_lammps_version(args.version)
print("Installing LAMMPS Python package version %s into site-packages folder" % verstr)
# we need to switch to the folder of the python package
olddir = os.path.abspath('.')
os.chdir(os.path.dirname(args.package))
from distutils.core import setup
from distutils.sysconfig import get_python_lib
import site
from sys import version_info
# remove any wheel files left over from previous calls
print("Purging existing wheels...")
for wheel in glob.glob('lammps-*.whl'):
print("deleting " + wheel)
os.remove(wheel)
if version_info.major >= 3:
pkgs = ['lammps', 'lammps.mliap']
else:
pkgs = ['lammps']
# copy shared object to the current folder so that
# it will show up in the installation at the expected location
os.putenv('LAMMPS_SHARED_LIB',os.path.basename(args.lib))
shutil.copy(args.lib,'lammps')
#Arguments common to global or user install -- everything but data_files
setup_kwargs= dict(name="lammps",
version=verstr,
author="Steve Plimpton",
author_email="sjplimp@sandia.gov",
url="https://www.lammps.org",
description="LAMMPS Molecular Dynamics Python package",
license="GPL",
packages=pkgs,
)
tryuser=False
# create a virtual environment for building the wheel
shutil.rmtree('buildwheel',True)
try:
sys.argv = ["setup.py","install"] # as if had run "python setup.py install"
setup_kwargs['data_files']=[(os.path.join(get_python_lib(), 'lammps'), [args.lib])]
setup(**setup_kwargs)
except: # lgtm [py/catch-base-exception]
tryuser=True
print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE)
txt = subprocess.check_output([sys.executable, '-m', 'virtualenv', 'buildwheel', '-p', sys.executable], stderr=subprocess.STDOUT, shell=False)
print(txt.decode('UTF-8'))
except subprocess.CalledProcessError as err:
sys.exit("Failed to create a virtualenv: {0}".format(err.output.decode('UTF-8')))
if tryuser:
# now run the commands to build the wheel. those must be in a separate script
# and run in subprocess, since this will use the virtual environment and
# there is no simple way to return from that in python.
os.system(sys.executable + ' makewheel.py')
# remove temporary folders and files
shutil.rmtree('buildwheel',True)
shutil.rmtree('build',True)
shutil.rmtree('lammps.egg-info',True)
os.remove(os.path.join('lammps',os.path.basename(args.lib)))
# stop here if we were asked not to install the wheel we created
if args.noinstall:
exit(0)
# install the wheel with pip. first try to install in the default environment.
# that will be a virtual environment, if active, or the system folder.
# recent versions of pip will automatically drop to use the user folder
# in case the system folder is not writable.
# we use a subprocess so we can catch an exception on failure.
# we need to check whether pip refused to install because of a
# version of the module previously installed with distutils. those
# must be uninstalled manually. We must not ignore this and drop
# back to install into a (forced) user folder.
print("Installing wheel")
for wheel in glob.glob('lammps-*.whl'):
try:
sys.argv = ["setup.py","install","--user"] # as if had run "python setup.py install --user"
setup_kwargs['data_files']=[(os.path.join(site.USER_SITE, 'lammps'), [args.lib])]
setup(**setup_kwargs)
except: # lgtm [py/catch-base-exception]
print("Installation into user site package folder failed.")
txt = subprocess.check_output([sys.executable, '-m', 'pip', 'install', '--force-reinstall', wheel], stderr=subprocess.STDOUT, shell=False)
print(txt.decode('UTF-8'))
continue
except subprocess.CalledProcessError as err:
errmsg = err.output.decode('UTF-8')
if errmsg.find("distutils installed"):
sys.exit(errmsg + "You need to uninstall the LAMMPS python module manually first.\n")
try:
print('Installing wheel into standard site-packages folder failed. Trying user folder now')
txt = subprocess.check_output([sys.executable, '-m', 'pip', 'install', '--user', '--force-reinstall', wheel], stderr=subprocess.STDOUT, shell=False)
print(txt.decode('UTF-8'))
except:
sys.exit('Failed to install wheel ' + wheel)
shutil.copy(wheel, olddir)
os.remove(wheel)

18
python/makewheel.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
import sys,os,shutil
# find python script to activate the virtual environment and source it
if sys.platform == 'win32':
virtenv=os.path.join('buildwheel','Scripts','activate_this.py')
else:
virtenv=os.path.join('buildwheel','bin','activate_this.py')
exec(open(virtenv).read(), {'__file__': virtenv})
# update pip and install all requirements to build the wheel
os.system('python -m pip install --upgrade pip')
os.system('python -m pip install --upgrade -r wheel_requirements.txt')
print("Building new binary wheel")
os.system('python -m build -n --wheel -o .')

3
python/pyproject.toml Normal file
View File

@ -0,0 +1,3 @@
[build-system]
requires = [ "setuptools>=42", "wheel" ]
build-backend = "setuptools.build_meta"

View File

@ -1,8 +1,9 @@
# this only installs the LAMMPS python package
# it assumes the LAMMPS shared library is already installed
from setuptools import setup
from setuptools.dist import Distribution
from sys import version_info
import os,time
import os,time,shutil
LAMMPS_PYTHON_DIR = os.path.dirname(os.path.realpath(__file__))
LAMMPS_DIR = os.path.dirname(LAMMPS_PYTHON_DIR)
LAMMPS_SOURCE_DIR = os.path.join(LAMMPS_DIR, 'src')
@ -21,18 +22,48 @@ def get_lammps_version():
t = time.strptime("".join(line[start_pos:end_pos].split()), "%d%b%Y")
return "{}.{}.{}".format(t.tm_year,t.tm_mon,t.tm_mday)
class BinaryDistribution(Distribution):
"""Wrapper to enforce creating a binary package"""
def has_ext_modules(foo):
return True
if version_info.major >= 3:
pkgs = ['lammps', 'lammps.mliap']
else:
pkgs = ['lammps']
with open("README", "r") as fh:
long_description = fh.read()
libname = os.environ.get("LAMMPS_SHARED_LIB")
if libname:
pkgdata = {'lammps': [ libname ]}
bdist = BinaryDistribution
else:
pkgdata = {}
bdist = Distribution
setup(
name = "lammps",
version = get_lammps_version(),
author = "Steve Plimpton",
author_email = "sjplimp@sandia.gov",
url = "https://www.lammps.org",
project_urls = {
"Bug Tracker": "https://github.com/lammps/lammps/issues",
},
description = "LAMMPS Molecular Dynamics Python package",
long_description = long_description,
long_description_content_type = "text/plain",
classifiers = [
"Programming Language :: Python :: 3",
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"Operating System :: OS Independent",
],
license = "GPL",
packages=pkgs,
packages = pkgs,
package_data = pkgdata,
distclass = bdist,
)

View File

@ -0,0 +1,4 @@
pip
build
wheel
setuptools

View File

@ -458,8 +458,7 @@ mpi-stubs:
sinclude ../lib/python/Makefile.lammps
install-python:
@rm -rf ../python/build
@$(PYTHON) ../python/install.py -v ../src/version.h \
-p ../python/lammps -l ../src/liblammps.so
@$(PYTHON) ../python/install.py -p ../python/lammps -l ../src/liblammps.so
# Create a tarball of src dir and packages

View File

@ -74,7 +74,7 @@ EOF
CUSTOM_PROMPT_ENV=/.singularity.d/env/99-zz_custom_prompt.sh
cat >$CUSTOM_PROMPT_ENV <<EOF
#!/bin/bash
PS1="[centos8:\u@\h] \W> "
PS1="[rocky8:\u@\h] \W> "
EOF
chmod 755 $CUSTOM_PROMPT_ENV

View File

@ -56,6 +56,7 @@ From: ubuntu:18.04
python3-pkg-resources \
python3-setuptools \
python3-virtualenv \
python3-venv \
rsync \
ssh \
texlive \

View File

@ -95,6 +95,7 @@ From: ubuntu:18.04
python3-pkg-resources \
python3-setuptools \
python3-virtualenv \
python3-venv \
rsync \
ssh \
vim-nox \

View File

@ -100,6 +100,7 @@ From: ubuntu:18.04
python3-pkg-resources \
python3-setuptools \
python3-virtualenv \
python3-venv \
rsync \
ssh \
vim-nox \

View File

@ -59,6 +59,7 @@ From: ubuntu:18.04
python3-pkg-resources \
python3-setuptools \
python3-virtualenv \
python3-venv \
rsync \
ssh \
vim-nox \

View File

@ -59,6 +59,7 @@ From: nvidia/cuda:11.4.2-devel-ubuntu18.04
python3-pkg-resources \
python3-setuptools \
python3-virtualenv \
python3-venv \
rsync \
ssh \
vim-nox \