From 7826b58f7369d5da9e1dba2160b696cab5739227 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 00:38:17 -0500 Subject: [PATCH 1/8] add check to lammps python module to check consistent versions between module and shared library --- python/install.py | 26 +++++++++++++++++++++++++- python/lammps/__init__.py | 4 ++++ python/lammps/core.py | 6 ++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/python/install.py b/python/install.py index 6765c33925..db3fea639d 100644 --- a/python/install.py +++ b/python/install.py @@ -10,7 +10,7 @@ build target in the conventional and CMake based build systems # copy LAMMPS shared library and lammps package to system dirs from __future__ import print_function -import sys,os,shutil +import sys,os,re,shutil from argparse import ArgumentParser parser = ArgumentParser(prog='install.py', @@ -90,11 +90,35 @@ def get_lammps_version(header): verstr = get_lammps_version(args.version) +# convert string version to numeric version +vernum = 0 +vregex = re.compile(r"([0-9]+)([A-Za-z]+)(2[0-9]+)") +m = vregex.match(verstr) +if (m): + month2num = { 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, 'May' : 5, 'Jun' : 6, + 'Jul' : 7, 'Aug' : 8, 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12 } + try: + vernum = int(m.group(3))*10000 + vernum += month2num[m.group(2)]*100 + vernum += int(m.group(1)) + except: + exit('Failure to parse version string: %s' % verstr) + print("Installing LAMMPS Python package version %s into site-packages folder" % verstr) # we need to switch to the folder of the python package os.chdir(os.path.dirname(args.package)) + + +# update version number in lammps module +vregex = re.compile(r".*(__version__ += +)[0-9]+") +with open(os.path.join('lammps','__init__.py'), "r+") as f: + content = f.read() + f.seek(0) + f.write(re.sub(vregex, lambda match: '{}{}'.format(match.group(1), vernum), content)) + f.truncate() + from distutils.core import setup from distutils.sysconfig import get_python_lib import site diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index b1c8306617..d79ebe3e9f 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -2,3 +2,7 @@ from .constants import * from .core import * from .data import * from .pylammps import * + +# automatically updated during installation + +__version__ = 20201224 diff --git a/python/lammps/core.py b/python/lammps/core.py index 6c1300ccf2..1ae6ff5286 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -381,6 +381,12 @@ class lammps(object): self._installed_packages = None self._available_styles = None + # check if liblammps version matches the installed python module version + import lammps + if lammps.__version__ != self.lib.lammps_version(self.lmp): + raise(AttributeError("LAMMPS Python module installed for LAMMPS version %d, but shared library is version %d" \ + % (lammps.__version__, self.lib.lammps_version(self.lmp)))) + # add way to insert Python callback for fix external self.callback = {} self.FIX_EXTERNAL_CALLBACK_FUNC = CFUNCTYPE(None, py_object, self.c_bigint, c_int, POINTER(self.c_tagint), POINTER(POINTER(c_double)), POINTER(POINTER(c_double))) From b53b993c681ec67af553a0d55dd83f294f8048fd Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 02:12:37 -0500 Subject: [PATCH 2/8] recover in-place usage by defaulting to version 0 and changing it back after installation --- python/install.py | 7 +++++++ python/lammps/__init__.py | 2 +- python/lammps/core.py | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/python/install.py b/python/install.py index db3fea639d..bd0874593f 100644 --- a/python/install.py +++ b/python/install.py @@ -150,3 +150,10 @@ if tryuser: setup(**setup_kwargs) except: print("Installation into user site package folder failed.") + +# restore __version__ == 0 for in place usage +with open(os.path.join('lammps','__init__.py'), "r+") as f: + content = f.read() + f.seek(0) + f.write(re.sub(vregex, lambda match: '{}{}'.format(match.group(1), 0), content)) + f.truncate() diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index d79ebe3e9f..e73e514d8c 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -5,4 +5,4 @@ from .pylammps import * # automatically updated during installation -__version__ = 20201224 +__version__ = 0 diff --git a/python/lammps/core.py b/python/lammps/core.py index 1ae6ff5286..1dc135359d 100644 --- a/python/lammps/core.py +++ b/python/lammps/core.py @@ -382,8 +382,9 @@ class lammps(object): self._available_styles = None # check if liblammps version matches the installed python module version + # but not for in-place usage, i.e. when the version is 0 import lammps - if lammps.__version__ != self.lib.lammps_version(self.lmp): + if lammps.__version__ > 0 and lammps.__version__ != self.lib.lammps_version(self.lmp): raise(AttributeError("LAMMPS Python module installed for LAMMPS version %d, but shared library is version %d" \ % (lammps.__version__, self.lib.lammps_version(self.lmp)))) From e706f75d179ce4aabd9a6834be9dba5db2010c8c Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 11:44:26 -0500 Subject: [PATCH 3/8] fix permissions --- examples/USER/reaction/create_atoms_polystyrene/in.grow_styrene | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 examples/USER/reaction/create_atoms_polystyrene/in.grow_styrene diff --git a/examples/USER/reaction/create_atoms_polystyrene/in.grow_styrene b/examples/USER/reaction/create_atoms_polystyrene/in.grow_styrene old mode 100755 new mode 100644 From 653c29624658154f09cda260aa1a0585f38d6520 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 12:29:14 -0500 Subject: [PATCH 4/8] document __version__ module member and version check --- doc/src/Python_module.rst | 17 +++++++++++++++++ doc/src/fix_flow_gauss.rst | 5 +++-- python/lammps/__init__.py | 10 ++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/doc/src/Python_module.rst b/doc/src/Python_module.rst index 8b4fbe1c2e..59be645cbd 100644 --- a/doc/src/Python_module.rst +++ b/doc/src/Python_module.rst @@ -26,6 +26,23 @@ There are multiple Python interface classes in the :py:mod:`lammps` module: .. _mpi4py_url: https://mpi4py.readthedocs.io +.. admonition:: Version check + :class: note + + The :py:mod:`lammps` module stores the version number of the LAMMPS + version it is installed from. When initializing the + :py:class:`lammps ` class, this version is checked to + be the same as the result from :py:func:`lammps.version`, the version + of the LAMMPS shared library that the module interfaces to. If the + they are not the same an AttributeError exception is raised since a + mismatch of versions (e.g. due to incorrect use of the + ``LD_LIBRARY_PATH`` or ``PYTHONPATH`` environment variables can lead + to crashes or data corruption and otherwise incorrect behavior. + +.. automodule:: lammps + :members: + :noindex: + ---------- The ``lammps`` class API diff --git a/doc/src/fix_flow_gauss.rst b/doc/src/fix_flow_gauss.rst index c7907432dc..67a0218c9b 100644 --- a/doc/src/fix_flow_gauss.rst +++ b/doc/src/fix_flow_gauss.rst @@ -165,8 +165,9 @@ LAMMPS was built with that package. See the :doc:`Build package Related commands """""""""""""""" -:doc:`fix addforce `, :doc:`compute temp/profile - `, :doc:`velocity ` +:doc:`fix addforce `, +:doc:`compute temp/profile `, +:doc:`velocity ` Default """"""" diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index e73e514d8c..be496167e8 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -1,3 +1,13 @@ +""" +LAMMPS module global members: + +.. data:: __version__ + + Numerical representation of the LAMMPS version this + module was taken from. Has the same format as the + result of :py:func:`lammps.version`. +""" + from .constants import * from .core import * from .data import * From 418135667fdd7341963995bd307b4435ead73b89 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 12:38:46 -0500 Subject: [PATCH 5/8] address a whole bunch of spelling issues that suddenly popped up. --- doc/src/Developer_notes.rst | 2 +- doc/src/fix_cmap.rst | 2 +- doc/src/fix_colvars.rst | 2 +- doc/src/fix_modify.rst | 4 ++-- doc/src/fix_orient.rst | 2 +- doc/src/fix_orient_eco.rst | 2 +- doc/src/fix_precession_spin.rst | 2 +- doc/src/fix_tgnh_drude.rst | 2 +- doc/src/fix_wall_ees.rst | 2 +- doc/utils/sphinx-config/false_positives.txt | 4 ++++ 10 files changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/src/Developer_notes.rst b/doc/src/Developer_notes.rst index d4fee7b9a0..ab2e3826f2 100644 --- a/doc/src/Developer_notes.rst +++ b/doc/src/Developer_notes.rst @@ -90,7 +90,7 @@ The fix must also do the following: The fix must also specify whether (by default) to include or exclude these contributions to the global/peratom energy/virial of the system. For the fix to include the contributions, set either of both of these -variables in the contructor: +variables in the constructor: * *thermo_energy* = 1, for global and peratom energy * *thermo_virial* = 1, for global and peratom virial diff --git a/doc/src/fix_cmap.rst b/doc/src/fix_cmap.rst index 94f8a903e9..892fd4ab41 100644 --- a/doc/src/fix_cmap.rst +++ b/doc/src/fix_cmap.rst @@ -103,7 +103,7 @@ uninterrupted fashion. The :doc:`fix_modify ` *energy* option is supported by this fix to add the potential energy of the CMAP interactions to both the global potential energy and peratom potential energies of the -sysstem as part of :doc:`thermodynamic output ` or +system as part of :doc:`thermodynamic output ` or output by the :doc:`compute pe/atom ` command. The default setting for this fix is :doc:`fix_modify energy yes `. diff --git a/doc/src/fix_colvars.rst b/doc/src/fix_colvars.rst index 7a238d3242..3f503410d3 100644 --- a/doc/src/fix_colvars.rst +++ b/doc/src/fix_colvars.rst @@ -115,7 +115,7 @@ in a pair of double quotes ("), or can span multiple lines when bracketed by a pair of triple double quotes (""", like python embedded documentation). This fix computes a global scalar which can be accessed by various -:doc:`output commands `. The scalar is the Covars +:doc:`output commands `. The scalar is the Colvars energy mentioned above. The scalar value calculated by this fix is "extensive". diff --git a/doc/src/fix_modify.rst b/doc/src/fix_modify.rst index 3f97b158e2..a6bac6ac44 100644 --- a/doc/src/fix_modify.rst +++ b/doc/src/fix_modify.rst @@ -83,7 +83,7 @@ appropriate fix. .. note:: - For most fixes that suppport the *energy* keyword, the default + For most fixes that support the *energy* keyword, the default setting is *no*. For a few it is *yes*, when a user would expect that to be the case. The doc page of each fix gives the default. @@ -108,7 +108,7 @@ option to include or exclude the contribution from fixes. .. note:: - For most fixes that suppport the *virial* keyword, the default + For most fixes that support the *virial* keyword, the default setting is *no*. For a few it is *yes*, when a user would expect that to be the case. The doc page of each fix gives the default. diff --git a/doc/src/fix_orient.rst b/doc/src/fix_orient.rst index 12f22403cd..3397261552 100644 --- a/doc/src/fix_orient.rst +++ b/doc/src/fix_orient.rst @@ -149,7 +149,7 @@ No information about this fix is written to :doc:`binary restart files The :doc:`fix_modify ` *energy* option is supported by this fix to add the potential energy of atom interactions with the -grain bounadry driving force to the global potential energy of the +grain boundary driving force to the global potential energy of the system as part of :doc:`thermodynamic output `. The default setting for this fix is :doc:`fix_modify energy no `. diff --git a/doc/src/fix_orient_eco.rst b/doc/src/fix_orient_eco.rst index 71d5a6de86..1db83338d4 100644 --- a/doc/src/fix_orient_eco.rst +++ b/doc/src/fix_orient_eco.rst @@ -103,7 +103,7 @@ files `. The :doc:`fix_modify ` *energy* option is supported by this fix to add the potential energy of atom interactions with the -grain bounadry driving force to the global potential energy of the +grain boundary driving force to the global potential energy of the system as part of :doc:`thermodynamic output `. The default setting for this fix is :doc:`fix_modify energy no `. diff --git a/doc/src/fix_precession_spin.rst b/doc/src/fix_precession_spin.rst index 17231d5686..5e818374a0 100644 --- a/doc/src/fix_precession_spin.rst +++ b/doc/src/fix_precession_spin.rst @@ -141,7 +141,7 @@ No information about this fix is written to :doc:`binary restart files `. The :doc:`fix_modify ` *energy* option is supported by -this fix to add the energy assocatiated with the spin precession +this fix to add the energy associated with the spin precession torque to the global potential energy of the system as part of :doc:`thermodynamic output `. The default setting for this fix is :doc:`fix_modify energy no `. diff --git a/doc/src/fix_tgnh_drude.rst b/doc/src/fix_tgnh_drude.rst index 6d11539dd2..1854655a82 100644 --- a/doc/src/fix_tgnh_drude.rst +++ b/doc/src/fix_tgnh_drude.rst @@ -240,7 +240,7 @@ compute temperature on a subset of atoms. keyword will be unaffected by the *temp* setting. The cumulative energy change in the system imposed by these fixes, due -to thermostatting and/or barostating, are included in the +to thermostatting and/or barostatting, are included in the :doc:`thermodynamic output ` keywords *ecouple* and *econserve*. See the :doc:`thermo_style ` doc page for details. diff --git a/doc/src/fix_wall_ees.rst b/doc/src/fix_wall_ees.rst index fde9fe7234..cf689f3a77 100644 --- a/doc/src/fix_wall_ees.rst +++ b/doc/src/fix_wall_ees.rst @@ -131,7 +131,7 @@ The :doc:`fix_modify ` *energy* option is supported by these fixes to add the energy of interaction between atoms and all the specified walls or region wall to the global potential energy of the system as part of :doc:`thermodynamic output `. The -default settings for thes fixes are :doc:`fix_modify energy no +default settings for these fixes are :doc:`fix_modify energy no `. The :doc:`fix_modify ` *respa* option is supported by diff --git a/doc/utils/sphinx-config/false_positives.txt b/doc/utils/sphinx-config/false_positives.txt index a2f8764aee..13282ebe9c 100644 --- a/doc/utils/sphinx-config/false_positives.txt +++ b/doc/utils/sphinx-config/false_positives.txt @@ -508,6 +508,7 @@ cpp cpu createatoms createAtoms +CreateIDs crespi Crespi Critchley @@ -788,6 +789,7 @@ ees eFF efield effm +eflag eflux eg Eggebrecht @@ -2681,6 +2683,7 @@ rfile rg Rg Rhaphson +Rhe rheological rheology rhodo @@ -3335,6 +3338,7 @@ verlet Verlet versa ves +vflag vhi vibrational Vij From e7bcd1ea432409a9a3297fde53f22bdf8dbda0d6 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 14:12:43 -0500 Subject: [PATCH 6/8] must purge python/build folder so we don't inherit outdated files --- cmake/CMakeLists.txt | 4 ++-- src/Makefile | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index c1fef4d4e1..2d259791f2 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -662,8 +662,8 @@ if(BUILD_SHARED_LIBS) endif() if (Python_EXECUTABLE) add_custom_target( - install-python - ${Python_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h + 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} diff --git a/src/Makefile b/src/Makefile index 7a5e1aa728..679cbe7b97 100644 --- a/src/Makefile +++ b/src/Makefile @@ -272,11 +272,13 @@ mpi-stubs: @cd STUBS; $(MAKE) clean; $(MAKE) # install LAMMPS shared lib and Python wrapper for Python usage -# include python package settings to -# automatically adapt name of python interpreter +# include python package settings to automatically adapt name of +# the python interpreter. must purge build folder to not install +# unwanted outdated files. 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 From 62a152e4a2a5767d20edd637e9b02fb1b095d66f Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 14:13:18 -0500 Subject: [PATCH 7/8] get version number from package version instead of rewriting the __init__.py file --- python/install.py | 33 +-------------------------------- python/lammps/__init__.py | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/python/install.py b/python/install.py index bd0874593f..6765c33925 100644 --- a/python/install.py +++ b/python/install.py @@ -10,7 +10,7 @@ build target in the conventional and CMake based build systems # copy LAMMPS shared library and lammps package to system dirs from __future__ import print_function -import sys,os,re,shutil +import sys,os,shutil from argparse import ArgumentParser parser = ArgumentParser(prog='install.py', @@ -90,35 +90,11 @@ def get_lammps_version(header): verstr = get_lammps_version(args.version) -# convert string version to numeric version -vernum = 0 -vregex = re.compile(r"([0-9]+)([A-Za-z]+)(2[0-9]+)") -m = vregex.match(verstr) -if (m): - month2num = { 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, 'May' : 5, 'Jun' : 6, - 'Jul' : 7, 'Aug' : 8, 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12 } - try: - vernum = int(m.group(3))*10000 - vernum += month2num[m.group(2)]*100 - vernum += int(m.group(1)) - except: - exit('Failure to parse version string: %s' % verstr) - print("Installing LAMMPS Python package version %s into site-packages folder" % verstr) # we need to switch to the folder of the python package os.chdir(os.path.dirname(args.package)) - - -# update version number in lammps module -vregex = re.compile(r".*(__version__ += +)[0-9]+") -with open(os.path.join('lammps','__init__.py'), "r+") as f: - content = f.read() - f.seek(0) - f.write(re.sub(vregex, lambda match: '{}{}'.format(match.group(1), vernum), content)) - f.truncate() - from distutils.core import setup from distutils.sysconfig import get_python_lib import site @@ -150,10 +126,3 @@ if tryuser: setup(**setup_kwargs) except: print("Installation into user site package folder failed.") - -# restore __version__ == 0 for in place usage -with open(os.path.join('lammps','__init__.py'), "r+") as f: - content = f.read() - f.seek(0) - f.write(re.sub(vregex, lambda match: '{}{}'.format(match.group(1), 0), content)) - f.truncate() diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index be496167e8..89ff30ead9 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -13,6 +13,37 @@ from .core import * from .data import * from .pylammps import * -# automatically updated during installation +# convert module string version to numeric version +def get_version_number(): + import re + from sys import version_info + vstring = None + if version_info.major == 3 and version_info.minor >= 8: + from importlib.metadata import version + try: + vstring = version('lammps') + except: pass + else: + from pkg_resources import get_distribution + try: + vstring = get_distribution('lammps').version + except: pass -__version__ = 0 + if not vstring: + return 0 + + vregex = re.compile(r"([0-9]+)([A-Za-z]+)(2[0-9]+)") + m = vregex.match(vstring) + + if (m): + month2num = { 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, 'May' : 5, 'Jun' : 6, + 'Jul' : 7, 'Aug' : 8, 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12 } + try: + vernum = int(m.group(3))*10000 + vernum += month2num[m.group(2)]*100 + vernum += int(m.group(1)) + except: + exit('Failure to parse version string: %s' % verstr) + return vernum + +__version__ = get_version_number() From 903433d9dd7aca6f8989b917c0d10801d96c4541 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 Feb 2021 14:22:30 -0500 Subject: [PATCH 8/8] use datetime module to convert string date to numeric date --- python/lammps/__init__.py | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/python/lammps/__init__.py b/python/lammps/__init__.py index 89ff30ead9..48839273c5 100644 --- a/python/lammps/__init__.py +++ b/python/lammps/__init__.py @@ -15,7 +15,7 @@ from .pylammps import * # convert module string version to numeric version def get_version_number(): - import re + from datetime import datetime from sys import version_info vstring = None if version_info.major == 3 and version_info.minor >= 8: @@ -32,18 +32,7 @@ def get_version_number(): if not vstring: return 0 - vregex = re.compile(r"([0-9]+)([A-Za-z]+)(2[0-9]+)") - m = vregex.match(vstring) - - if (m): - month2num = { 'Jan' : 1, 'Feb' : 2, 'Mar' : 3, 'Apr' : 4, 'May' : 5, 'Jun' : 6, - 'Jul' : 7, 'Aug' : 8, 'Sep' : 9, 'Oct' : 10, 'Nov' : 11, 'Dec' : 12 } - try: - vernum = int(m.group(3))*10000 - vernum += month2num[m.group(2)]*100 - vernum += int(m.group(1)) - except: - exit('Failure to parse version string: %s' % verstr) - return vernum + d = datetime.strptime(vstring, "%d%b%Y") + return d.year*10000 + d.month*100 + d.day __version__ = get_version_number()