Episode 3: LAMMPS with EESSI on EuroHPC

In our Leonardo Booster tests, EESSI offered newer CPU LAMMPS builds and an older CUDA build. We checked their packages and tried accessing them through a container. This episode shows the setup that worked and the problems we found.

Before you start

Prerequisites

  • A Leonardo Booster account and a Slurm allocation with GPU access.

  • Familiarity with environment modules and the package checks in Episode 1: Installing LAMMPS on EuroHPC.

  • A project scratch directory with space for a container image and its cache.

  • Access to profile/global, eessi/1.0, and singularityce/4.3.3 on Leonardo.

  • Internet access from a login node to prepare the official EESSI image.

Tested configuration

The checks below were performed on Leonardo Booster on 13 October 2026:

Component

Tested version

GPU and NVIDIA driver

A100-SXM-64GB; 535.274.02

EESSI CPU target

x86_64/intel/icelake

EESSI accelerator target

accel/nvidia/cc80

EESSI releases inspected

2023.06, 2025.06, 2026.06

Leonardo access module

eessi/1.0, under profile/global

Container runtime

SingularityCE 4.3.3

Official EESSI image

docker://ghcr.io/eessi/build-node:debian12

EESSI launcher revision

6327b3a782f4a17ec54cc2f809624980e33a2f64

The image supplies an environment for accessing EESSI. Application modules come from the mounted EESSI repository. Using a container does not automatically provide newer LAMMPS modules.

1. Understand the EESSI selection

EESSI is the European Environment for Scientific Software Installations. It provides software builds for different CPU and accelerator architectures and forms the basis of the EuroHPC Federation Platform’s Federated Software Catalog.

EESSI selects compatible builds by detecting the hardware on the node where you initialize it. The EuroHPC system name does not select the software. Site configuration determines how the repository is mounted and how host libraries, such as the NVIDIA driver, are exposed.

Keep three choices separate:

Choice

What it controls

Access method

How the EESSI repository becomes available.

EESSI release

Which software collection you inspect.

CPU and accelerator targets

Which compatible builds are visible.

An EESSI release name such as 2025.06 is not a LAMMPS version. Read the full module name and check the executable before choosing an installation.

Create a working directory within your project scratch space:

mkdir -p eessi-lammps-work
cd eessi-lammps-work
export EESSI_LAMMPS_WORKDIR="$PWD"

As you complete the steps, the directory layout will be:

eessi-lammps-work/
├── inventory.sbatch             # native EESSI module inspection
├── native-lammps-modules-*.txt   # recorded module lists
├── software-layer-scripts/      # official EESSI launcher
├── images/                      # downloaded container image
├── cache/                       # container download cache
├── tmp/                         # image preparation files
├── container-storage/           # launcher state and private container home
├── inspect-container.sh         # checks performed inside the container
├── container.sbatch             # container job
└── container-lammps-modules-*.txt

2. Access EESSI on Leonardo Booster

Check the system-specific instructions

The EFP Leonardo instructions describe compute-node access using a Slurm job name containing _CVMFS_, followed by EESSI initialization. They also retain a warning about non-interactive and multi-node usage.

In our tests, the job-name trigger alone did not mount EESSI in either a batch job or an interactive Booster allocation. The site-provided eessi/1.0 launcher did mount the repository successfully on allocated compute nodes. The recipe below uses the site launcher.

Record the available modules

Save the following as inventory.sbatch in the project root. Replace the account placeholder with your allocation account and submit from this directory:

--qos=boost_qos_dbg selects Leonardo Booster’s debug Quality of Service (QoS) for short tests within the boost_usr_prod partition. It has a maximum walltime of 30 minutes and higher scheduling priority than the normal QoS; allocation time still depends on resource availability. For production runs, remove or replace this directive with a QoS appropriate to your allocation and adjust the time limit. Check the current Leonardo scheduling limits.

#!/bin/bash
#SBATCH --job-name=eessi-lammps-inventory
#SBATCH --partition=boost_usr_prod
# Debug QoS for short tests; maximum walltime 30 minutes.
#SBATCH --qos=boost_qos_dbg
#SBATCH --account=EUHPC_XXX_XXX
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --gres=gpu:1
#SBATCH --mem=8G
#SBATCH --time=00:10:00

set -eo pipefail
cd "$SLURM_SUBMIT_DIR"
module load profile/global
module load eessi/1.0

test -d /cvmfs/software.eessi.io/versions
ls /cvmfs/software.eessi.io/versions

for version in 2023.06 2025.06 2026.06; do
  module --force purge
  if ! module load "EESSI/$version"; then
    printf 'EESSI %s is unavailable\n' "$version"
    continue
  fi
  module -t avail 2>&1 | grep -E '^LAMMPS/[0-9]' | sort -u \
    > "native-lammps-modules-$version.txt" || true
  printf '\nEESSI %s LAMMPS modules:\n' "$version"
  cat "native-lammps-modules-$version.txt"
done
cd "$EESSI_LAMMPS_WORKDIR"
sbatch inventory.sbatch

Read the selected CPU and accelerator targets in the Slurm output, then compare the recorded module lists with the table below.

Note

Loading eessi/1.0 both mounts the repository and initializes EESSI. Run it on an allocated compute node; our login nodes had no EESSI mount.

3. Choose a LAMMPS build

The following modules were visible for Ice Lake and A100 (cc80) targets in both the native environment and the container:

EESSI release

LAMMPS module

2023.06

LAMMPS/2Aug2023_update2-foss-2023a-kokkos

2023.06

LAMMPS/2Aug2023_update2-foss-2023a-kokkos-CUDA-12.1.1

2023.06

LAMMPS/29Aug2024-foss-2023b-kokkos

2025.06

LAMMPS/22Jul2025-foss-2024a-kokkos

2025.06

LAMMPS/22Jul2025_update4-foss-2025b-kokkos

2026.06

No LAMMPS modules found for the selected targets.

The table records the modules available for Ice Lake and A100 on the test date. Use your job’s output to check the current list.

Check the executable’s capabilities

The presence of kokkos in a module name does not establish CUDA support. Our container checks produced:

Tested LAMMPS build

KOKKOS backends

Other checks

22Jul2025_update4-foss-2025b-kokkos

OpenMP, Serial

ML-IAP, ML-SNAP, PYTHON; ML-IAP Python import passed.

2Aug2023_update2-foss-2023a-kokkos-CUDA-12.1.1

CUDA, OpenMP

ML-IAP, ML-SNAP, PYTHON; ML-IAP Python import passed.

The native CUDA module failed its NVIDIA host-library check. It loaded successfully inside the container when we bound the host EESSI repository, as shown below.

Our checks covered module lists, CUDA driver initialization, lmp -h, and the lammps.mliap import on one A100. We did not run molecular dynamics or MACE inference with these EESSI installations.

MACE support

These LAMMPS modules include ML-IAP, but their Python environments contained no MACE, PyTorch, CuPy, or cuEquivariance. For a MACE build and copper simulation, follow Episode 2: LAMMPS with MACE on Leonardo Booster, which includes an energy/force comparison with Python MACE.

4. Prepare the official EESSI container

Run these downloads on a login node. The compute-node checks will reuse the local image rather than pulling it during an allocation.

Download the launcher and image

cd "$EESSI_LAMMPS_WORKDIR"
git clone https://github.com/EESSI/software-layer-scripts.git
git -C software-layer-scripts checkout 6327b3a782f4a17ec54cc2f809624980e33a2f64

module load profile/global
module load singularityce/4.3.3
singularity --version

mkdir -p images cache tmp
export SINGULARITY_CACHEDIR="$PWD/cache"
export SINGULARITY_TMPDIR="$PWD/tmp"
singularity pull images/eessi-debian12.sif \
  docker://ghcr.io/eessi/build-node:debian12

sha256sum images/eessi-debian12.sif > images/eessi-debian12.sif.sha256

The image is published by EESSI. The debian12 tag can change, so keep the launcher revision and the checksum of your downloaded SIF with your records. Initial download and conversion can take several minutes.

Choose the repository access method

The official launcher can mount EESSI inside the container using FUSE. In our independent-mount test, the container started and accessed the GPU, but CVMFS failed to initialize the root catalogue. That test could not list EESSI modules.

The working recipe instead binds the repository mounted by Leonardo’s site launcher into the container. It therefore still needs a working host EESSI mount. The launcher uses --repository None to disable its repository mounting, then receives an explicit read-only bind for the existing repository.

Singularity also reported a squashfuse permission failure in our tests and fell back to extracting the SIF. That fallback allowed the container to run; it was separate from the failed CVMFS catalogue fetch.

5. Inspect EESSI inside the container

Save the inspection script

Save the following as inspect-container.sh in the project root. The job binds that directory to /work inside the container:

#!/bin/bash
set -eo pipefail
cd /work
ls /cvmfs/software.eessi.io/versions
nvidia-smi --query-gpu=name,driver_version --format=csv,noheader

/usr/bin/python3 - <<'PY'
import ctypes

cuda = ctypes.CDLL("libcuda.so.1")
assert cuda.cuInit(0) == 0, "CUDA driver initialization failed"
count = ctypes.c_int()
assert cuda.cuDeviceGetCount(ctypes.byref(count)) == 0
assert count.value == 1, "This example expects one visible GPU"
print("CUDA driver check passed; visible GPUs:", count.value)
PY

source /cvmfs/software.eessi.io/versions/2025.06/init/lmod/bash

for version in 2023.06 2025.06 2026.06; do
  module --force purge
  export EESSI_ACCELERATOR_TARGET_OVERRIDE=accel/nvidia/cc80
  if ! module load "EESSI/$version"; then
    printf 'EESSI %s is unavailable\n' "$version"
    continue
  fi
  module -t avail 2>&1 | grep -E '^LAMMPS/[0-9]' | sort -u \
    > "container-lammps-modules-$version.txt" || true
  cat "container-lammps-modules-$version.txt"
done

module --force purge
export EESSI_ACCELERATOR_TARGET_OVERRIDE=accel/nvidia/cc80
module load EESSI/2023.06
module load LAMMPS/2Aug2023_update2-foss-2023a-kokkos-CUDA-12.1.1

timeout 45 mpirun --mca pml ob1 --mca btl self,tcp -np 1 lmp -h \
  > container-lammps-help.txt 2>&1

grep -a 'KOKKOS package API' container-lammps-help.txt
sed -n '/Installed packages:/,/List of individual/p' container-lammps-help.txt
python -c 'import lammps.mliap; print("ML-IAP Python import passed")'

The container detected Ice Lake automatically, but EESSI did not automatically identify the accelerator there. The explicit cc80 override matches the A100 verified by nvidia-smi and the CUDA driver check. It selects the GPU module collection for that hardware.

We used this mpirun command only for a one-process help check. For simulations, use a centre-supported MPI setup and test it at the node count you plan to use.

Save the container job

Save the following as container.sbatch in the project root. Replace the account placeholder before submitting:

#!/bin/bash
#SBATCH --job-name=eessi-lammps-container
#SBATCH --partition=boost_usr_prod
# Debug QoS for short tests; maximum walltime 30 minutes.
#SBATCH --qos=boost_qos_dbg
#SBATCH --account=EUHPC_XXX_XXX
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=2
#SBATCH --gres=gpu:1
#SBATCH --mem=16G
#SBATCH --time=00:15:00

set -eo pipefail
cd "$SLURM_SUBMIT_DIR"
module load profile/global
module load singularityce/4.3.3

CONTAINER_RUNTIME_DIR="$(dirname "$(command -v singularity)")"
CONTAINER_RUNTIME_LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}"
module load eessi/1.0

test -d /cvmfs/software.eessi.io/versions
export PATH="$CONTAINER_RUNTIME_DIR:$PATH"
export LD_LIBRARY_PATH="$CONTAINER_RUNTIME_LD_LIBRARY_PATH"
export SINGULARITY_CACHEDIR="$PWD/cache"
export SINGULARITY_TMPDIR="${TMPDIR:-/tmp}"
export SINGULARITYENV_CUDA_VISIBLE_DEVICES="${CUDA_VISIBLE_DEVICES:-0}"
export EESSI_DO_NOT_MOUNT_CVMFS_CONFIG_CERN_CH=1
mkdir -p container-storage

./software-layer-scripts/eessi_container.sh \
  --container "$PWD/images/eessi-debian12.sif" \
  --storage "$PWD/container-storage" \
  --repository None \
  --extra-bind-paths "$PWD:/work,/cvmfs/software.eessi.io:/cvmfs/software.eessi.io:ro" \
  --nvidia run --pass-through --cleanenv \
  --mode exec /bin/bash /work/inspect-container.sh

Loading the site EESSI environment changes the host module environment. The script retains the Singularity executable directory and library path selected before that change. --cleanenv keeps the host software environment from being inherited wholesale inside the container; the allocated GPU selection is passed explicitly through SINGULARITYENV_CUDA_VISIBLE_DEVICES.

Submit and compare

cd "$EESSI_LAMMPS_WORKDIR"
sbatch container.sbatch

After the job finishes, inspect its output and compare the recorded lists:

for version in 2023.06 2025.06 2026.06; do
  diff -u "native-lammps-modules-$version.txt" \
    "container-lammps-modules-$version.txt"
done

Our lists matched for all three releases. An empty diff output means the two lists match. The Slurm output should also show CUDA driver check passed, KOKKOS package API: CUDA OpenMP, and ML-IAP Python import passed.

Completion checklist

  • EESSI is accessible on the allocated compute node.

  • The selected release, CPU target, and GPU target are recorded.

  • The native and container module lists have been inspected and compared.

  • The container can initialize the CUDA driver on the allocated GPU.

  • LAMMPS reports the required packages and hardware backend.

  • The ML-IAP Python interface imports.

Further reading