Skip to content

generate version from the source files for LAMMPS when using software-commit #3485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
May 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5989313
generate version from the source files for using software-commit
Oct 14, 2024
c91686b
generate version from the source files for using software-commit
Oct 14, 2024
4beab69
generate version from the source files for using software-commit
Oct 14, 2024
ab990fb
generate version from the source files for using software-commit
Oct 14, 2024
bdf7024
generate version from the source files for using software-commit
Oct 14, 2024
787b080
generate version from the source files for using software-commit
Oct 14, 2024
c60c7c8
fix exception
Oct 14, 2024
3d295a9
fix re.split by space
Oct 14, 2024
55dc794
resolve merge conflict
Jan 30, 2025
1b45d17
Fix using --module-only when using different software-commit
Jan 31, 2025
ac72ee8
make CI happy
Jan 31, 2025
2cf92b6
Update easybuild/easyblocks/l/lammps.py
laraPPr Feb 3, 2025
66f5f23
Update easybuild/easyblocks/l/lammps.py
laraPPr Feb 3, 2025
c76d006
Update easybuild/easyblocks/l/lammps.py
laraPPr Feb 3, 2025
3725813
Update easybuild/easyblocks/l/lammps.py
laraPPr Feb 3, 2025
fcd111e
small tweaks to LAMMPS easyblock, mostly code cleanup
boegel Feb 5, 2025
1c0d6e2
remove version from lammpsdir
smoors Feb 8, 2025
5049fa7
Merge branch 'develop' into LAMMPS
Feb 11, 2025
3ac58fd
fix --sanity-check-only
Mar 3, 2025
9f3996a
make the hound happy
Mar 3, 2025
292c98c
make the hound even happier
Mar 3, 2025
4ca2f03
Merge branch 'easybuilders:develop' into LAMMPS
laraPPr Apr 18, 2025
5f7bf0f
Merge branch 'develop' into LAMMPS
boegel May 24, 2025
79ac0db
tweak translate_lammps_version
boegel May 24, 2025
400e534
fix check whether cur_version is set in LAMMPS sanity check step
boegel May 24, 2025
5290d43
remove duplicate extra_options in LAMMPS easyblock
boegel May 24, 2025
e92475b
don't check for LICENSE + version.h in sanity check for LAMMPS, since…
boegel May 24, 2025
9448184
fix prepare step in LAMMPS easyblock
boegel May 24, 2025
4a26691
remove duplicate update_kokkos_cpu_mapping in LAMMPS easyblock + add …
boegel May 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 74 additions & 38 deletions easybuild/easyblocks/l/lammps.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
from easybuild.framework.easyconfig import CUSTOM, MANDATORY
from easybuild.tools.build_log import EasyBuildError, print_warning, print_msg
from easybuild.tools.config import build_option
from easybuild.tools.filetools import copy_dir, mkdir
from easybuild.tools.filetools import copy_dir, copy_file, mkdir, read_file
from easybuild.tools.modules import get_software_root, get_software_version
from easybuild.tools.run import run_shell_cmd
from easybuild.tools.systemtools import AARCH64, get_cpu_architecture, get_shared_lib_ext
Expand Down Expand Up @@ -159,11 +159,8 @@
_log = fancylogger.getLogger('easyblocks.lammps')


def translate_lammps_version(version):
def translate_lammps_version(version, path=None):
"""Translate the LAMMPS version into something that can be used in a comparison"""
items = [x for x in re.split('(\\d+)', version) if x]
if len(items) < 3:
raise ValueError("Version %s does not have (at least) 3 elements" % version)
month_map = {
"JAN": '01',
"FEB": '02',
Expand All @@ -178,7 +175,26 @@ def translate_lammps_version(version):
"NOV": '11',
"DEC": '12'
}
return '.'.join([items[2], month_map[items[1].upper()], '%02d' % int(items[0])])
items = [x for x in re.split('(\\d+)', version) if x]

try:
return '.'.join([items[2], month_map[items[1].upper()], '%02d' % int(items[0])])
except (IndexError, KeyError):
# avoid failing miserably under --module-only --force
if path and os.path.exists(path) and os.listdir(path):
version_file = os.path.join(path, 'src', 'version.h')
if os.path.exists(version_file):
txt = read_file(os.path.join(path, 'src', 'version.h'))
result = re.search(r'(?<=LAMMPS_VERSION ")\d+ \S+ \d+', txt)
if result:
day, month, year = result.group().split(' ')
else:
raise EasyBuildError(f"Failed to parse LAMMPS version: '{txt}'")
return '.'.join([year, month_map[month.upper()], '%02d' % int(day)])
else:
raise EasyBuildError(f"Expected to find version file at {version_file}, but it doesn't exist")
else:
raise ValueError("LAMMPS version {version} cannot be translated")


class EB_LAMMPS(CMakeMake):
Expand All @@ -194,28 +210,23 @@ def __init__(self, *args, **kwargs):
cuda_toolchain = hasattr(self.toolchain, 'COMPILER_CUDA_FAMILY')
self.cuda = cuda_dep or cuda_toolchain

# version 1.3.2 is used in the test suite to check easyblock can be initialised
if self.version != '1.3.2':
self.cur_version = translate_lammps_version(self.version)
else:
self.cur_version = self.version
self.ref_version = translate_lammps_version(ref_version)
self.cur_version = None

self.pkg_prefix = 'PKG_'
if LooseVersion(self.cur_version) >= LooseVersion(self.ref_version):
self.pkg_user_prefix = self.pkg_prefix
else:
self.pkg_user_prefix = self.pkg_prefix + 'USER-'
def update_kokkos_cpu_mapping(self):
"""
Update mapping to Kokkos CPU targets based on LAMMPS version
"""
if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('31Mar2017')):
self.kokkos_cpu_mapping['neoverse_n1'] = 'ARMV81'
self.kokkos_cpu_mapping['neoverse_v1'] = 'ARMV81'

if LooseVersion(self.cur_version) >= LooseVersion(self.ref_version):
self.kokkos_prefix = 'Kokkos'
else:
self.kokkos_prefix = 'KOKKOS'
for cc in KOKKOS_GPU_ARCH_TABLE.keys():
KOKKOS_GPU_ARCH_TABLE[cc] = KOKKOS_GPU_ARCH_TABLE[cc].lower().title()
if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('21sep2021')):
self.kokkos_cpu_mapping['a64fx'] = 'A64FX'
self.kokkos_cpu_mapping['zen4'] = 'ZEN3'

self.kokkos_cpu_mapping = copy.deepcopy(KOKKOS_CPU_MAPPING)
self.update_kokkos_cpu_mapping()
if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('2Aug2023')):
self.kokkos_cpu_mapping['icelake'] = 'ICX'
self.kokkos_cpu_mapping['sapphirerapids'] = 'SPR'

@staticmethod
def extra_options(**kwargs):
Expand All @@ -231,23 +242,36 @@ def extra_options(**kwargs):
extra_vars['separate_build_dir'][0] = True
return extra_vars

def update_kokkos_cpu_mapping(self):
def prepare_step(self, *args, **kwargs):
"""Custom prepare step for LAMMPS."""
super().prepare_step(*args, **kwargs)

if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('31Mar2017')):
self.kokkos_cpu_mapping['neoverse_n1'] = 'ARMV81'
self.kokkos_cpu_mapping['neoverse_v1'] = 'ARMV81'
# version 1.3.2 is used in the test suite to check easyblock can be initialised
if self.version != '1.3.2':
# take into account that build directory may not be available (in case of --module-only)
if os.path.exists(self.start_dir) and os.listdir(self.start_dir):
self.cur_version = translate_lammps_version(self.version, path=self.start_dir)
else:
self.cur_version = translate_lammps_version(self.version, path=self.installdir)
else:
self.cur_version = self.version
self.ref_version = translate_lammps_version(ref_version)

if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('21sep2021')):
self.kokkos_cpu_mapping['a64fx'] = 'A64FX'
self.kokkos_cpu_mapping['zen4'] = 'ZEN3'
self.pkg_prefix = 'PKG_'
if LooseVersion(self.cur_version) >= LooseVersion(self.ref_version):
self.pkg_user_prefix = self.pkg_prefix
else:
self.pkg_user_prefix = self.pkg_prefix + 'USER-'

if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('2Aug2023')):
self.kokkos_cpu_mapping['icelake'] = 'ICX'
self.kokkos_cpu_mapping['sapphirerapids'] = 'SPR'
if LooseVersion(self.cur_version) >= LooseVersion(self.ref_version):
self.kokkos_prefix = 'Kokkos'
else:
self.kokkos_prefix = 'KOKKOS'
for cc in KOKKOS_GPU_ARCH_TABLE.keys():
KOKKOS_GPU_ARCH_TABLE[cc] = KOKKOS_GPU_ARCH_TABLE[cc].lower().title()

def prepare_step(self, *args, **kwargs):
"""Custom prepare step for LAMMPS."""
super().prepare_step(*args, **kwargs)
self.kokkos_cpu_mapping = copy.deepcopy(KOKKOS_CPU_MAPPING)
self.update_kokkos_cpu_mapping()

# Unset LIBS when using both KOKKOS and CUDA - it will mix lib paths otherwise
if self.cfg['kokkos'] and self.cuda:
Expand Down Expand Up @@ -464,12 +488,20 @@ def configure_step(self, **kwargs):
def install_step(self):
"""Install LAMMPS and examples/potentials."""
super().install_step()

# Copy LICENSE and version file so these can be used with `--module-only`
version_file = os.path.join(self.start_dir, 'src', 'version.h')
copy_file(version_file, os.path.join(self.installdir, 'src', 'version.h'))
license_file = os.path.join(self.start_dir, 'LICENSE')
copy_file(license_file, os.path.join(self.installdir, 'LICENSE'))

# Copy over the examples so we can repeat the sanity check
# (some symlinks may be broken)
examples_dir = os.path.join(self.start_dir, 'examples')
copy_dir(examples_dir, os.path.join(self.installdir, 'examples'), symlinks=True)
potentials_dir = os.path.join(self.start_dir, 'potentials')
copy_dir(potentials_dir, os.path.join(self.installdir, 'potentials'))

if LooseVersion(self.cur_version) >= LooseVersion(translate_lammps_version('2Aug2023')):
# From ver 2Aug2023:
# "make install in a CMake based installation will no longer install
Expand Down Expand Up @@ -500,6 +532,10 @@ def install_step(self):
def sanity_check_step(self, *args, **kwargs):
"""Run custom sanity checks for LAMMPS files, dirs and commands."""

# Set cur_version when running --sanity-check-only
if self.cur_version is None:
self.cur_version = translate_lammps_version(self.version, path=self.installdir)

# Output files need to go somewhere (and has to work for --module-only as well)
execution_dir = tempfile.mkdtemp()

Expand Down
23 changes: 23 additions & 0 deletions test/easyblocks/easyblock_specific.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import easybuild.tools.options as eboptions
import easybuild.easyblocks.generic.pythonpackage as pythonpackage
import easybuild.easyblocks.l.lammps as lammps
import easybuild.easyblocks.p.python as python
from easybuild.base.testing import TestCase
from easybuild.easyblocks.generic.cmakemake import det_cmake_version
Expand Down Expand Up @@ -463,6 +464,28 @@ def test_symlink_dist_site_packages(self):
self.assertTrue(os.path.isdir(lib64_site_path))
self.assertFalse(os.path.islink(lib64_site_path))

def test_translate_lammps_version(self):
"""Test translate_lammps_version function from LAMMPS easyblock"""
lammps_versions = {
'23Jun2022': '2022.06.23',
'2Aug2023_update2': '2023.08.02',
'29Aug2024': '2024.08.29',
'29Aug2024_update2': '2024.08.29',
'28Oct2024': '2024.10.28',
}
for key in lammps_versions:
self.assertEqual(lammps.translate_lammps_version(key), lammps_versions[key])

version_file = os.path.join(self.tmpdir, 'src', 'version.h')
version_txt = '\n'.join([
'#define LAMMPS_VERSION "2 Apr 2025"',
'#define LAMMPS_UPDATE "Development"',
])
write_file(version_file, version_txt)

self.assertEqual(lammps.translate_lammps_version('d3adb33f', path=self.tmpdir), '2025.04.02')
self.assertEqual(lammps.translate_lammps_version('devel', path=self.tmpdir), '2025.04.02')


def suite():
"""Return all easyblock-specific tests."""
Expand Down