mirror of
https://github.com/cp2k/cp2k.git
synced 2026-07-21 06:25:15 -04:00
1655 lines
61 KiB
Bash
Executable file
1655 lines
61 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
# Purpose: Build CP2K using Spack and CMake locally within the folder CP2K_ROOT
|
|
# which defaults to the current working directory. This should be a
|
|
# "cp2k/" folder containing the CP2K source tree which can be download with
|
|
#
|
|
# > git clone https://github.com/cp2k/cp2k.git cp2k
|
|
#
|
|
# and after
|
|
#
|
|
# > cd cp2k
|
|
#
|
|
# this script can be run in subshell using the default options with
|
|
#
|
|
# > ./make_cp2k.sh
|
|
#
|
|
# The flags -h or --help print the available options.
|
|
#
|
|
# The first run will take longer as it will build all CP2K dependencies
|
|
# with Spack. The Spack installation is kept fully local in the subfolder
|
|
# cp2k/spack which corresponds to the tools/toolchain/install folder
|
|
# created by the CP2K toolchain.
|
|
#
|
|
# Subsequent runs of the script will use the software stack from that
|
|
# cp2k/spack/ folder.
|
|
#
|
|
# A rebuild of all CP2K dependencies can be enforced simply by removing
|
|
# or renaming the folder cp2k/spack. The latter allows for keeping different
|
|
# software stacks (see also -bd and -bd_only flags).
|
|
#
|
|
# It is recommended to store already compiled packages in a cache (default).
|
|
# This will accelerate the (re)build of the CP2K dependencies with Spack
|
|
# significantly (see -uc flag).
|
|
#
|
|
# After the CP2K dependencies are built with Spack, CP2K itself is built
|
|
# and installed using CMake in the subfolders cp2k/build and cp2k/install,
|
|
# respectively.
|
|
#
|
|
# Subsequent runs of the script will use the CMake configuration in the
|
|
# subfolder cp2k/build. A rebuild of CP2K from scratch can be enforced
|
|
# by removing or renaming that subfolder.
|
|
#
|
|
# A CP2K regression run can be launched automatically by adding the flag
|
|
# -t "" (or --test ""). This flag expects a string with the TESTOPTS, e.g.
|
|
#
|
|
# > ./make_cp2k.sh -t "--maxtasks 8 --restrictdir QS/regtest-gpw-1"
|
|
#
|
|
# Alternatively, the script cp2k/install/bin/run_tests can be launched
|
|
# after a successful CP2K build. Usage examples are printed at the end.
|
|
|
|
# Authors: Matthias Krack (MK)
|
|
|
|
# Version: 2.0
|
|
|
|
# Facilitate the deugging of this script
|
|
set -uo pipefail
|
|
|
|
# Retrieve script name
|
|
SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
|
|
|
|
# Check if the script is sourced or run in a subshell
|
|
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
|
|
echo "${SCRIPT_NAME}: Running script in sourcing mode"
|
|
echo "${SCRIPT_NAME}: All changes from this script will become effective within the current shell"
|
|
EXIT_CMD="return"
|
|
else
|
|
echo "${SCRIPT_NAME}: Running script in subshell mode"
|
|
echo "${SCRIPT_NAME}: Changes from this script in the shell environment are lost after completion"
|
|
EXIT_CMD="exit"
|
|
fi
|
|
|
|
# Check platform
|
|
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
echo "ERROR: A build for Apple macOS (Darwin, Homebrew) is not supported yet,"
|
|
echo " but CP2K can be built within a container using podman."
|
|
echo " Check the Dockerfiles in the folder cp2k/tools/docker like"
|
|
echo " Dockerfile.test_spack_openmpi-psmp and the usage description in their header"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Help finding ldconfig
|
|
if ! command -v ldconfig &> /dev/null; then
|
|
PATH="${PATH}:/sbin"
|
|
fi
|
|
|
|
# Check if all mandatory packages are installed in the environment
|
|
for package in awk bzip2 find g++ gcc gfortran git gzip ldconfig make patch python3 tar wget xz; do
|
|
if ! command -v "${package}" &> /dev/null; then
|
|
echo "ERROR: The package \"${package}\" is mandatory to build CP2K with Spack/CMake"
|
|
echo " Install the missing package and re-run the script"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
done
|
|
|
|
# Disable python bytecode generation to suppress __pycache__ folder creation
|
|
export PYTHONDONTWRITEBYTECODE=1
|
|
|
|
# Print OS info if available
|
|
if [[ -f /etc/os-release ]]; then
|
|
echo ""
|
|
cat /etc/os-release
|
|
fi
|
|
|
|
# Check bash version
|
|
if ((BASH_VERSINFO < 4)); then
|
|
echo ""
|
|
echo "ERROR: The employed bash version ${BASH_VERSION} is too old (from 2004)"
|
|
echo " Install a newer bash version"
|
|
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
echo "HINT: Use the bash command provided by Homebrew with Apple"
|
|
echo " /opt/homebrew/bin should precede /bin/bash in the PATH"
|
|
echo " In sourcing mode, run /opt/homebrew/bin/bash first before sourcing this script"
|
|
fi
|
|
${EXIT_CMD} 1
|
|
elif ((BASH_VERSINFO < 5)); then
|
|
echo -e "\nWARNING: The employed bash version ${BASH_VERSION} is quite old (from 2009)"
|
|
else
|
|
echo -e "\nINFO: Using bash version ${BASH_VERSION}"
|
|
fi
|
|
|
|
# Check if the python3 version is new enough for spack
|
|
if ! python3 -c 'import sys; sys.exit(not(sys.version_info >= (3, 10)))'; then
|
|
echo ""
|
|
echo "ERROR: Python version is NOT >= 3.10 (needed for Spack)"
|
|
echo " Found only $(python3 -V)"
|
|
${EXIT_CMD} 1
|
|
else
|
|
echo -e "\nINFO: Found $(python3 -V)"
|
|
fi
|
|
|
|
# Default values
|
|
BUILD_DEPS="if_needed"
|
|
BUILD_DEPS_ONLY="no"
|
|
BUILD_SHARED_LIBS="${BUILD_SHARED_LIBS:-ON}"
|
|
CP2K_BUILD_TYPE="${CP2K_BUILD_TYPE:-Release}"
|
|
DEPS_BUILD_TYPE="${DEPS_BUILD_TYPE:-Release}"
|
|
CMAKE_FEATURE_FLAG_ALL="-DCP2K_USE_EVERYTHING=ON" # all features are activated by default
|
|
CMAKE_FEATURE_FLAGS="-DCP2K_BLAS_VENDOR=OpenBLAS" # LAPACK/BLAS from OpenBLAS by default
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_FFTW3=ON" # FFTW3 is always activated unless explicitly disabled
|
|
CMAKE_FEATURE_FLAG_MPI="-DCP2K_USE_MPI=ON" # MPI is switched on by default
|
|
CMAKE_FEATURE_FLAGS_GPU="-DCP2K_USE_SPLA_GEMM_OFFLOADING=ON"
|
|
CRAY="no"
|
|
CUDA_SM_CODE=0
|
|
GCC_VERSION="auto"
|
|
GPU_MODEL="none"
|
|
HELP="no"
|
|
INSTALL_MESSAGE="NEVER"
|
|
MPI_MODE="mpich"
|
|
if command -v nproc &> /dev/null; then
|
|
MAX_PROCS=$(nproc)
|
|
NUM_PROCS=${NUM_PROCS:-${MAX_PROCS}}
|
|
else
|
|
MAX_PROCS=-1
|
|
NUM_PROCS=${NUM_PROCS:-8}
|
|
fi
|
|
NUM_PACKAGES=2
|
|
NVCC_VERSION=0
|
|
REBUILD_CP2K="no"
|
|
RUN_TEST="no"
|
|
SED_PATTERN_LIST=""
|
|
TESTOPTS=""
|
|
USE_CACHE="folder"
|
|
USE_EXTERNALS="no"
|
|
USE_OPENCL="no"
|
|
VERBOSE=0
|
|
VERBOSE_FLAG="--quiet"
|
|
VERBOSE_MAKEFILE="OFF"
|
|
VERBOSE_SPACK=""
|
|
|
|
export CP2K_ENV="cp2k_env"
|
|
export CP2K_ROOT=${CP2K_ROOT:-${PWD}}
|
|
export CP2K_VERSION="${CP2K_VERSION:-psmp}"
|
|
|
|
export BUILD_PATH="${BUILD_PATH:-${CP2K_ROOT}}"
|
|
export INSTALL_PREFIX="${INSTALL_PREFIX:-${CP2K_ROOT}/install}"
|
|
|
|
# Parse flags
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-bd | --build_deps | --build_dependencies)
|
|
BUILD_DEPS="always"
|
|
shift 1
|
|
;;
|
|
-bd_only | --build_deps_only | --build_dependencies_only)
|
|
BUILD_DEPS="always"
|
|
BUILD_DEPS_ONLY="yes"
|
|
shift 1
|
|
;;
|
|
-bp | --build_path)
|
|
if (($# > 1)); then
|
|
BUILD_PATH="$(realpath "${2}")"
|
|
else
|
|
echo "ERROR: No build path argument found for flag \"${1}\""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-bsl | --build_static_libcp2k)
|
|
BUILD_SHARED_LIBS="OFF"
|
|
shift 1
|
|
;;
|
|
-bt | --build_type)
|
|
CP2K_BUILD_TYPE="${2}"
|
|
case "${CP2K_BUILD_TYPE}" in
|
|
Debug)
|
|
CP2K_VERSION="${CP2K_VERSION/smp/dbg}"
|
|
;;
|
|
Release | RelWithDebInfo)
|
|
CP2K_VERSION="${CP2K_VERSION/dbg/smp}"
|
|
;;
|
|
esac
|
|
shift 2
|
|
;;
|
|
-cray)
|
|
CRAY="yes"
|
|
shift 1
|
|
;;
|
|
-cv | --cp2k_version)
|
|
if (($# > 1)); then
|
|
case "${2,,}" in
|
|
pdbg | psmp | sdbg | ssmp | ssmp-static)
|
|
CP2K_VERSION="${2,,}"
|
|
# Set build type
|
|
case "${CP2K_VERSION}" in
|
|
pdbg | sdbg)
|
|
CP2K_BUILD_TYPE="Debug"
|
|
DEPS_BUILD_TYPE="RelWithDebInfo"
|
|
;;
|
|
psmp | ssmp | ssmp-static)
|
|
CP2K_BUILD_TYPE="Release"
|
|
DEPS_BUILD_TYPE="Release"
|
|
;;
|
|
esac
|
|
# Disable MPI for a serial CP2K binary
|
|
case "${CP2K_VERSION}" in
|
|
sdbg | ssmp | ssmp-static)
|
|
MPI_MODE="no"
|
|
CMAKE_FEATURE_FLAG_MPI="-DCP2K_USE_MPI=OFF"
|
|
;;
|
|
esac
|
|
# Apply specific package selection for statically linked binaries
|
|
case "${CP2K_VERSION}" in
|
|
ssmp-static)
|
|
CMAKE_FEATURE_FLAG_ALL="-DCP2K_USE_EVERYTHING=ON"
|
|
for package in libfci libint2 libxc libxs spglib vori tblite; do
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_${package^^}=ON"
|
|
done
|
|
for package in ace deepmd gauxc greenx hdf5 libgint libtorch pexsi trexio; do
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_${package^^}=OFF"
|
|
done
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
echo "ERROR: Invalid CP2K version \"${2}\" specified (choose pdbg, psmp, sdbg, ssmp, or ssmp-static)"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "ERROR: No argument found for flag \"${1}\" (choose pdbg, psmp, sdbg, ssmp, or ssmp-static)"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-df | --disable | --disable_feature | -ef | --enable | --enable_feature)
|
|
if (($# > 1)); then
|
|
case "${1}" in
|
|
-df | --disable | --disable_feature)
|
|
ON_OFF="OFF"
|
|
SUBST="s/^ /#/'"
|
|
;;
|
|
-ef | --enable | --enable_feature)
|
|
ON_OFF="ON"
|
|
SUBST="s/#/ /'"
|
|
;;
|
|
esac
|
|
case "${2,,}" in
|
|
all)
|
|
# Enable or disable all features
|
|
CMAKE_FEATURE_FLAG_ALL="-DCP2K_USE_EVERYTHING=${ON_OFF}"
|
|
for package in adios2 cosma deepmdkit dla-future dla-future-fortran elpa \
|
|
gauxc greenx hdf5 libfabric libfci libint libvdwxc libsmeagol libvori \
|
|
libxc libxs libxsmm mimic-mcl openpmd-api pace pexsi plumed py-torch sirius \
|
|
spfft spglib spla tblite trexio; do
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"${package}@/ ${SUBST}"
|
|
done
|
|
# dbcsr must use blas as fallback when libxs/libxsmm is disabled
|
|
if [[ "${ON_OFF}" == "OFF" ]]; then
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"smm=libxs\"/ s/libxs/blas/'"
|
|
fi
|
|
;;
|
|
ace | cosma | deepmd | dftd4 | dlaf | elpa | fftw3 | gauxc | greenx | hdf5 | libfci | \
|
|
libgint | libint2 | libsmeagol | libtorch | libxc | libxs | mimic | openpmd | pexsi | \
|
|
plumed | spglib | tblite | trexio | vori)
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_${2^^}=${ON_OFF}"
|
|
# Translate package selection to sed pattern
|
|
case "${2,,}" in
|
|
ace)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"p${2,,}@/ ${SUBST}"
|
|
;;
|
|
cosma | elpa | greenx | hdf5 | libfci | libsmeagol | libxc | pexsi | plumed | \
|
|
spglib | trexio)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"${2,,}@/ ${SUBST}"
|
|
;;
|
|
deepmd)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"${2,,}kit@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "ON" ]]; then
|
|
# DeePMD-kit requires libtorch
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_LIBTORCH=${ON_OFF}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"py-torch@/ ${SUBST}"
|
|
fi
|
|
;;
|
|
dftd4)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"${2,,}@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "ON" ]]; then
|
|
echo "INFO: tblite is disabled to avoid conflicts when dftd4 is used"
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_TBLITE=OFF"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"tblite@/ s/^ /#/'"
|
|
fi
|
|
;;
|
|
dlaf)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"dla-future.*@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "ON" ]]; then
|
|
SED_PATTERN_LIST+=" -e 's/\~dlaf/\+dlaf/'"
|
|
else
|
|
SED_PATTERN_LIST+=" -e 's/\+dlaf/\~dlaf/'"
|
|
fi
|
|
;;
|
|
fftw3)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"fftw@/ ${SUBST}"
|
|
;;
|
|
gauxc)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"${2,,}@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "ON" ]]; then
|
|
# GauXC requires libtorch
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_LIBTORCH=${ON_OFF}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"py-torch@/ ${SUBST}"
|
|
fi
|
|
;;
|
|
libint2)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"libint@/ ${SUBST}"
|
|
;;
|
|
libtorch)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"py-torch@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "OFF" ]]; then
|
|
# DeePMD-kit and GauXC require libtorch
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_DEEPMD=${ON_OFF}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"deepmdkit@/ ${SUBST}"
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_GAUXC=${ON_OFF}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"gauxc@/ ${SUBST}"
|
|
fi
|
|
;;
|
|
libxs)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"libxs@/ ${SUBST}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"libxsmm@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "OFF" ]]; then
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"smm=${2,,}\"/ s/${2,,}/blas/'"
|
|
fi
|
|
;;
|
|
mimic)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"mimic-mcl@/ ${SUBST}"
|
|
;;
|
|
openpmd | adios2)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"adios2@/ ${SUBST}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"openpmd-api@/ ${SUBST}"
|
|
;;
|
|
tblite)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"${2,,}@/ ${SUBST}"
|
|
if [[ "${ON_OFF}" == "ON" ]]; then
|
|
echo "INFO: dftd4 is disabled to avoid conflicts when tblite is used"
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_DFTD4=OFF"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"dftd4@/ s/^ /#/'"
|
|
fi
|
|
;;
|
|
vori)
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"lib${2,,}@/ ${SUBST}"
|
|
;;
|
|
esac
|
|
;;
|
|
libvdwxc | spfft | spla | sirius)
|
|
echo "WARNING: You have enabled or disabled one of the packages libvdwxc, spfft, spla, sirius"
|
|
echo " which means that the other packages will also be enabled or disabled"
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_LIBVDWXC=${ON_OFF} -DCP2K_USE_SpFFT=${ON_OFF}"
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_SPLA=${ON_OFF} -DCP2K_USE_SIRIUS=${ON_OFF}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"libvdwxc@/ ${SUBST}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"spfft@/ ${SUBST}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"spla@/ ${SUBST}"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"sirius@/ ${SUBST}"
|
|
;;
|
|
cray_pm_accel_energy | cusolver_mp | spla_gemm_offloading | unified_memory)
|
|
CMAKE_FEATURE_FLAGS_GPU+=" -DCP2K_USE_${2^^}=${ON_OFF}"
|
|
;;
|
|
dbm_gpu | elpa_gpu | grid_gpu | pw_gpu)
|
|
CMAKE_FEATURE_FLAGS_GPU+=" -DCP2K_ENABLE_${2^^}=${ON_OFF}"
|
|
;;
|
|
none)
|
|
# do nothing
|
|
;;
|
|
*)
|
|
echo "ERROR: Unknown CP2K feature \"${2}\" specified"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "ERROR: No feature found for flag \"${1}\""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-gv | --gcc_version)
|
|
if (($# > 1)); then
|
|
case "${2}" in
|
|
1[0-6])
|
|
GCC_VERSION="${2}"
|
|
;;
|
|
*)
|
|
echo "ERROR: Invalid GCC version \"${2}\" specified (choose from 10 to 16)"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "ERROR: No argument found for flag \"${1}\" (choose a GCC version)"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-gm | -gpu | --gpu_model)
|
|
if (($# > 1)); then
|
|
case "${2^^}" in
|
|
P100 | V100 | T400 | A100 | A40 | H100 | H200 | GH200)
|
|
GPU_MODEL="${2^^}"
|
|
case "${GPU_MODEL}" in
|
|
P100)
|
|
CUDA_SM_CODE=60
|
|
;;
|
|
V100)
|
|
CUDA_SM_CODE=70
|
|
;;
|
|
T400)
|
|
CUDA_SM_CODE=75
|
|
;;
|
|
A100)
|
|
CUDA_SM_CODE=80
|
|
;;
|
|
A40)
|
|
CUDA_SM_CODE=86
|
|
;;
|
|
H100 | H200 | GH200)
|
|
CUDA_SM_CODE=90
|
|
;;
|
|
esac
|
|
;;
|
|
60 | 70 | 75 | 80 | 86 | 87 | 89 | 90 | 120 | 121)
|
|
CUDA_SM_CODE=${2}
|
|
;;
|
|
NONE)
|
|
GPU_MODEL="${2,,}"
|
|
;;
|
|
*)
|
|
echo -e "\nERROR: Unknown GPU model \"${2}\" specified (choose <CUDA SM code>, P100, V100, T400, A100, A40, H100, H200, GH200 or none)\n"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
echo -e "\nERROR: No argument found for flag \"${1}\" (choose <CUDA SM code>, P100, V100, T400, A100, A40, H100, H200, GH200 or none)\n"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-h | --help)
|
|
HELP="yes"
|
|
shift 1
|
|
;;
|
|
-ip | --install_path | --install_prefix)
|
|
if (($# > 1)); then
|
|
INSTALL_PREFIX="$(realpath "${2}")"
|
|
else
|
|
echo "ERROR: No install path argument found for flag \"${1}\""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-j)
|
|
if (($# > 1)); then
|
|
case "${2}" in
|
|
-*)
|
|
shift 1
|
|
;;
|
|
[0-9]*)
|
|
NUM_PROCS="${2}"
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "ERROR: The -j flag can only be followed by an integer number, found \"${2}\""
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
shift 1
|
|
fi
|
|
;;
|
|
-j[0-9]*)
|
|
NUM_PROCS="${1#-j}"
|
|
shift 1
|
|
;;
|
|
-mpi | --mpi_mode)
|
|
if (($# > 1)); then
|
|
case "${2,,}" in
|
|
mpich | openmpi)
|
|
CMAKE_FEATURE_FLAG_MPI="-DCP2K_USE_MPI=ON"
|
|
MPI_MODE="${2,,}"
|
|
;;
|
|
no | none | off)
|
|
CMAKE_FEATURE_FLAG_MPI="-DCP2K_USE_MPI=OFF"
|
|
MPI_MODE="no"
|
|
;;
|
|
*)
|
|
echo "ERROR: Unknown MPI mode \"${2}\" specified (choose mpich, openmpi, or no)"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "ERROR: No argument found for flag \"${1}\""
|
|
echo " The MPI mode is required (choose mpich, openmpi, or no)"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-np | --num_packages)
|
|
if (($# > 1)); then
|
|
case "${2}" in
|
|
-*)
|
|
shift 1
|
|
;;
|
|
[0-9]*)
|
|
NUM_PACKAGES="${2}"
|
|
shift 2
|
|
;;
|
|
*)
|
|
echo "ERROR: The -np flag can only be followed by an integer number, found \"${2}\""
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
shift 1
|
|
fi
|
|
;;
|
|
-opencl)
|
|
USE_OPENCL="yes"
|
|
shift 1
|
|
;;
|
|
-rc | --rebuild_cp2k)
|
|
REBUILD_CP2K="yes"
|
|
shift 1
|
|
;;
|
|
-t | --test)
|
|
RUN_TEST="yes"
|
|
if (($# > 1)); then
|
|
TESTOPTS="${2}"
|
|
else
|
|
echo "ERROR: No argument found for flag \"${1}\""
|
|
echo " A string argument with the TESTOPTS (even an empty one \"\") is required"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-uc | --use_cache)
|
|
if (($# > 1)); then
|
|
case "${2,,}" in
|
|
folder | minio | no | none)
|
|
USE_CACHE="${2,,}"
|
|
;;
|
|
*)
|
|
echo "ERROR: Invalid cache mode \"${2}\" specified (choose folder, minio or no)"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "ERROR: No argument found for flag \"${1}\" (choose folder, minio or no)"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shift 2
|
|
;;
|
|
-ue | --use_externals)
|
|
USE_EXTERNALS="yes"
|
|
shift 1
|
|
;;
|
|
-v | --verbose)
|
|
VERBOSE=1
|
|
INSTALL_MESSAGE="LAZY"
|
|
VERBOSE_FLAG="--verbose"
|
|
VERBOSE_MAKEFILE="ON"
|
|
VERBOSE_SPACK="--verbose"
|
|
shift 1
|
|
;;
|
|
--)
|
|
shift 1
|
|
break
|
|
;;
|
|
-*)
|
|
echo "ERROR: Unknown option \"${1}\" specified"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Remove leading zeros from NUM_PACKAGES and NUM_PROCS
|
|
NUM_PACKAGES=$(awk '{print $1+0}' <<< "${NUM_PACKAGES}")
|
|
NUM_PROCS=$(awk '{print $1+0}' <<< "${NUM_PROCS}")
|
|
|
|
# Check if we are working within a docker or podman container
|
|
[[ -f /.dockerenv || -f /run/.containerenv ]] && IN_CONTAINER="yes" || IN_CONTAINER="no"
|
|
|
|
# Assemble CMake feature flag list
|
|
CMAKE_FEATURE_FLAGS="${CMAKE_FEATURE_FLAG_ALL} ${CMAKE_FEATURE_FLAG_MPI} ${CMAKE_FEATURE_FLAGS}"
|
|
|
|
# DLA-Future does not work with MPICH yet
|
|
case "${MPI_MODE}" in
|
|
mpich | openmpi)
|
|
if [[ "${CMAKE_FEATURE_FLAGS}" == *"-DCP2K_USE_EVERYTHING=ON"* ]] ||
|
|
[[ "${CMAKE_FEATURE_FLAGS}" == *"-DCP2K_USE_DLAF=ON"* ]]; then
|
|
echo -e "\nINFO: DLA-Future does not work with ${MPI_MODE^^} yet and is disabled"
|
|
CMAKE_FEATURE_FLAGS+=" -DCP2K_USE_DLAF=OFF"
|
|
SED_PATTERN_LIST+=" -e '/\s*-\s+\"dla-future.*@/ s/^ /#/'"
|
|
SED_PATTERN_LIST+=" -e 's/\+dlaf/\~dlaf/'"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Clean CMake feature flag list from repeated entries and keep only the last definition
|
|
declare -A last=()
|
|
order=()
|
|
# First pass: record the last occurrence of each flag
|
|
for flag in ${CMAKE_FEATURE_FLAGS}; do
|
|
name=${flag%=*}
|
|
last[${name}]=${flag}
|
|
order+=("${name}")
|
|
done
|
|
# Second pass: output only the last definition per flag
|
|
# but respecting original order of last appearance
|
|
declare -A seen=()
|
|
out=()
|
|
for name in "${order[@]}"; do
|
|
if [[ -z ${seen[${name}]+_} ]]; then
|
|
seen[${name}]=1
|
|
out+=("${last[${name}]}")
|
|
fi
|
|
done
|
|
CMAKE_FEATURE_FLAGS="$(printf '%s\n' "${out[*]}")"
|
|
|
|
export BUILD_DEPS BUILD_DEPS_ONLY BUILD_SHARED_LIBS CMAKE_FEATURE_FLAGS CMAKE_FEATURE_FLAGS_GPU CP2K_BUILD_TYPE \
|
|
CRAY CUDA_SM_CODE DEPS_BUILD_TYPE GCC_VERSION GPU_MODEL IN_CONTAINER INSTALL_MESSAGE MPI_MODE NUM_PACKAGES \
|
|
NUM_PROCS REBUILD_CP2K RUN_TEST TESTOPTS USE_CACHE USE_OPENCL VERBOSE VERBOSE_FLAG VERBOSE_MAKEFILE VERBOSE_SPACK
|
|
|
|
# Show help if requested
|
|
if [[ "${HELP}" == "yes" ]]; then
|
|
echo ""
|
|
echo "Usage: ${SCRIPT_NAME} [-bd | --build_deps]"
|
|
echo " [-bd_only | --build_deps_only]"
|
|
echo " [-bp | --build_path PATH]"
|
|
echo " [-bsl | --build_static_libcp2k]"
|
|
echo " [-bt | --build_type (Debug | Release | RelWithDebInfo)]"
|
|
echo " [-cray]"
|
|
echo " [-cv | --cp2k_version (pdbg | psmp | sdbg | ssmp | ssmp-static)]"
|
|
echo " [-df | --disable | --disable_feature (all | FEATURE | PACKAGE | none)"
|
|
echo " [-ef | --enable | --enable_feature (all | FEATURE | PACKAGE | none)"
|
|
echo " [-gm | -gpu | --gpu_model (<CUDA SM code> | P100 | V100 | T400 | A100 | H100 | H200 | GH200 | none)]"
|
|
echo " [-gv | --gcc_version (10 | 11 | 12 | 13 | 14 | 15 | 16)]"
|
|
echo " [-h | --help]"
|
|
echo " [-ip | --install_path PATH]"
|
|
echo " [-j #PROCESSES]"
|
|
echo " [-mpi | --mpi_mode (mpich | no | openmpi)]"
|
|
echo " [-np | --num_packages #PACKAGES]"
|
|
echo " [-rc | --rebuild_cp2k]"
|
|
echo " [-t | --test \"TESTOPTS\"]"
|
|
echo " [-uc | --use_cache (folder | minio | no | none)]"
|
|
echo " [-ue | --use_externals]"
|
|
echo " [-v | --verbose]"
|
|
echo ""
|
|
echo "Flags:"
|
|
echo " --build_deps : Force a rebuild of all CP2K dependencies from scratch (removes the spack folder)"
|
|
echo " --build_deps_only : Rebuild ONLY the CP2K dependencies from scratch (removes the spack folder)"
|
|
echo " --build_path : Define the CP2K build path (default: ${CP2K_ROOT})"
|
|
echo " --build_static_libcp2k: Build a static CP2K library libcp2k.a instead of the default shared one libcp2k.so"
|
|
echo " --build_type : Set preferred CMake build type for CP2K (default: \"Release\")"
|
|
echo " --cp2k_version : CP2K version to be built (default: \"psmp\")"
|
|
echo " -cray : Use Cray specific spack configuration"
|
|
echo " --enable_feature : Enable feature or package (default: all)"
|
|
echo " --disable_feature : Disable feature or package"
|
|
echo " --help : Print this help information"
|
|
echo " --gcc_version : Use the specified GCC version (default: automatically decided by spack)"
|
|
echo " --gpu_model : Select GPU model (default: none)"
|
|
echo " --install_path : Define the CP2K installation path (default: ./install)"
|
|
echo " -j : Maximum number of processes used in parallel"
|
|
echo " --mpi_mode : Set preferred MPI mode (default: \"mpich\")"
|
|
echo " --num_packages : Maximum number of packages built by spack in parallel (default: 4)"
|
|
echo " -opencl : Perform build with OpenCL support"
|
|
echo " --rebuild_cp2k : Rebuild CP2K: removes the build folder (default: no)"
|
|
echo " --test : Perform a regression test run after a successful build"
|
|
echo " --use_cache : Use a \"folder\", a \"MinIO\" object storage container (requires podman) or \"no\" cache"
|
|
echo " Set the environment variable SPACK_CACHE to specify the folder name, e.g."
|
|
echo " SPACK_CACHE=\"file://${CP2K_ROOT}/spack_cache\" (default)"
|
|
echo " --use_externals : Use external packages installed on the host system. This results in much"
|
|
echo " faster build times, but it can also cause conflicts with outdated packages"
|
|
echo " pulled in from the host system, e.g. old python or gcc versions"
|
|
echo " --verbose : Write verbose output"
|
|
echo ""
|
|
echo "Hints:"
|
|
echo " - Remove the folder ${CP2K_ROOT}/build to (re)build CP2K from scratch"
|
|
echo " (see also --rebuild_cp2k flag)"
|
|
echo " - Remove the folder ${CP2K_ROOT}/spack to (re)build CP2K and all its dependencies from scratch"
|
|
echo " (see also --build_deps flag)"
|
|
echo " - The folder ${CP2K_ROOT}/install is updated after each successful run"
|
|
echo ""
|
|
echo "Packages: all | ace | cosma | deepmd | dftd4 | dlaf | elpa | fftw3 | gauxc | greenx | hdf5 | libfci |"
|
|
echo " libgint | libint | libsmeagol | libtorch | libvdwxc | libxs | mimic | openpmd | pexsi | plumed |"
|
|
echo " sirius | spfft | spglib | spla | tblite | trexio | vori "
|
|
echo ""
|
|
echo "Features: cray_pm_accel_energy | cusolver_mp | dbm_gpu | elpa_gpu | grid_gpu | pw_gpu |"
|
|
echo " spla_gemm_offloading | unified_memory"
|
|
echo ""
|
|
${EXIT_CMD}
|
|
fi
|
|
|
|
echo ""
|
|
echo "BUILD_DEPS = ${BUILD_DEPS}"
|
|
echo "BUILD_DEPS_ONLY = ${BUILD_DEPS_ONLY}"
|
|
echo "BUILD_PATH = ${BUILD_PATH}"
|
|
echo "BUILD_SHARED_LIBS = ${BUILD_SHARED_LIBS}"
|
|
echo "CP2K_BUILD_TYPE = ${CP2K_BUILD_TYPE}"
|
|
echo "CP2K_VERSION = ${CP2K_VERSION}"
|
|
echo "CRAY = ${CRAY}"
|
|
echo "DEPS_BUILD_TYPE = ${DEPS_BUILD_TYPE}"
|
|
echo "GCC_VERSION = ${GCC_VERSION}"
|
|
if ((CUDA_SM_CODE > 0)); then
|
|
echo "GPU = ${GPU_MODEL} (CUDA SM code: ${CUDA_SM_CODE})"
|
|
else
|
|
echo "GPU = ${GPU_MODEL}"
|
|
fi
|
|
echo "INSTALL_PREFIX = ${INSTALL_PREFIX}"
|
|
echo "INSTALL_MESSAGE = ${INSTALL_MESSAGE}"
|
|
echo "IN_CONTAINER = ${IN_CONTAINER}"
|
|
echo "MPI_MODE = ${MPI_MODE}"
|
|
echo "NUM_PACKAGES = ${NUM_PACKAGES} (packages are built by spack concurrently)"
|
|
echo "NUM_PROCS = ${NUM_PROCS} (processes)"
|
|
echo "Physical cores = $(lscpu -p=Core,Socket | grep -v '#' | sort -u | wc -l) (host view)"
|
|
echo "REBUILD_CP2K = ${REBUILD_CP2K}"
|
|
echo "RUN_TEST = ${RUN_TEST}"
|
|
if [[ "${RUN_TEST}" == "yes" ]]; then
|
|
echo "TESTOPTS = \"${TESTOPTS}\""
|
|
fi
|
|
echo "USE_CACHE = ${USE_CACHE}"
|
|
echo "USE_EXTERNALS = ${USE_EXTERNALS}"
|
|
echo "USE_OPENCL = ${USE_OPENCL}"
|
|
echo "VERBOSE_FLAG = ${VERBOSE_FLAG}"
|
|
echo "VERBOSE_MAKEFILE = ${VERBOSE_MAKEFILE}"
|
|
echo "VERBOSE = ${VERBOSE}"
|
|
if (($# > 0)); then
|
|
echo "Remaining args =" "$@" "(not used)"
|
|
fi
|
|
echo ""
|
|
echo "LD_LIBRARY_PATH = ${LD_LIBRARY_PATH:-}"
|
|
echo ""
|
|
echo "PATH = ${PATH:-}"
|
|
echo ""
|
|
echo "CMAKE_FEATURE_FLAGS = ${CMAKE_FEATURE_FLAGS}"
|
|
echo ""
|
|
|
|
((VERBOSE > 0)) && echo -e "SED_PATTERN_LIST = ${SED_PATTERN_LIST}\n"
|
|
|
|
# Check if a valid number for the packages to be built by spack in parallel is given
|
|
if ((NUM_PACKAGES < 1)); then
|
|
echo -e "\nERROR: The requested number of packages to be built by spack in parallel should be larger than 0, found \"${NUM_PACKAGES}\""
|
|
${EXIT_CMD} 1
|
|
elif ((NUM_PROCS > 0)) && ((NUM_PACKAGES > NUM_PROCS)); then
|
|
echo -e "\nERROR: The requested number of packages to be built in parallel by spack (${NUM_PACKAGES}) is larger than the requested number of processes (${NUM_PROCS})"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Check if a valid number of processes is requested
|
|
if ((NUM_PROCS < 1)); then
|
|
echo "ERROR: The requested number of processes should be larger than 0, found \"${NUM_PROCS}\""
|
|
${EXIT_CMD} 1
|
|
elif ((MAX_PROCS > 0)) && ((NUM_PROCS > MAX_PROCS)); then
|
|
echo "WARNING: The requested number of processes (${NUM_PROCS}) is larger than the detected number of CPU cores (${MAX_PROCS})"
|
|
fi
|
|
|
|
# Check if a valid CMake build type is selected for the dependencies
|
|
case "${DEPS_BUILD_TYPE^}" in
|
|
Release | RelWithDebInfo)
|
|
true
|
|
;;
|
|
Debug)
|
|
echo "ERROR: The CMake build type \"${DEPS_BUILD_TYPE}\" is not supported for building the dependencies"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
*)
|
|
echo "ERROR: Invalid CMake build type \"${DEPS_BUILD_TYPE}\" selected for building the dependencies"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
|
|
# Check if a valid CMake build type is selected for CP2K
|
|
case "${CP2K_BUILD_TYPE^}" in
|
|
Debug | Release | RelWithDebInfo)
|
|
true
|
|
;;
|
|
*)
|
|
echo "ERROR: Invalid CMake build type \"${CP2K_BUILD_TYPE}\" selected for building CP2K"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
|
|
# Check if a valid MPI type is selected
|
|
case "${MPI_MODE}" in
|
|
mpich | openmpi)
|
|
if [[ "${CP2K_VERSION}" == "ssmp"* ]]; then
|
|
echo "ERROR: MPI type \"${MPI_MODE}\" specified for building a serial CP2K binary"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
;;
|
|
no)
|
|
if [[ "${CP2K_VERSION}" == "psmp" ]]; then
|
|
echo "ERROR: MPI type \"${MPI_MODE}\" specified for building an MPI-parallel CP2K binary"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
;;
|
|
*)
|
|
echo "ERROR: Invalid MPI type \"${MPI_MODE}\" selected"
|
|
echo " Choose from (mpich | no | openmpi)"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
|
|
# Check if CP2K_VERSION and the selected features are compatible
|
|
case "${CP2K_VERSION}" in
|
|
ssmp | ssmp-static)
|
|
for package in cosma dlaf elpa libfabric libsmeagol mimic openpmd pexsi plumed sirius spla; do
|
|
if [[ "${CMAKE_FEATURE_FLAGS}" == *" -DCP2K_USE_${package^^}=ON"* ]]; then
|
|
echo -e "ERROR: The feature ${package^^} is not available for building serial CP2K binaries (${CP2K_VERSION})\n"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
done
|
|
# Further exclusions are needed for statically linked serial CP2K binaries
|
|
if [[ "${CP2K_VERSION}" == "ssmp-static" ]]; then
|
|
for package in ace deepmd greenx hdf5 libgint libtorch trexio; do
|
|
if [[ "${CMAKE_FEATURE_FLAGS}" == *" -DCP2K_USE_${package^^}=ON"* ]]; then
|
|
echo -e "ERROR: The feature ${package^^} is not available for building statically linked serial CP2K binaries (${CP2K_VERSION})\n"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
done
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Perform CUDA GPU related settings
|
|
if ((CUDA_SM_CODE > 0)); then
|
|
if command -v nvcc &> /dev/null; then
|
|
CUDA_VERSION=$(nvcc -V | sed -n 's/.*release \([0-9.]*\).*/\1/p')
|
|
NVCC_VERSION=$(awk -v x="${CUDA_VERSION}" 'BEGIN{print 10*x}')
|
|
else
|
|
echo -e "\nERROR: No CUDA toolkit installation found (nvcc compiler not found)\n"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
# Check if the selected CUDA SM code is valid when the nvidia-smi command is available
|
|
if command -v nvidia-smi &> /dev/null; then
|
|
echo -e "NVIDIA driver installation found:\n"
|
|
nvidia-smi
|
|
HOST_CUDA_SM_CODE=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader | tail -n 1 | awk '{print 10*$1}')
|
|
if ((CUDA_SM_CODE > HOST_CUDA_SM_CODE)); then
|
|
echo ""
|
|
echo "ERROR: The requested CUDA SM code (${CUDA_SM_CODE}) is larger than the maximum"
|
|
echo " CUDA SM code (${HOST_CUDA_SM_CODE}) supported by the host system"
|
|
echo ""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
else
|
|
echo "INFO: No NVIDIA driver installation found (nvidia-smi not found)"
|
|
fi
|
|
# Check GPU support by the CUDA SDK
|
|
if ((NVCC_VERSION < 128)) && ((CUDA_SM_CODE > 90)); then
|
|
echo ""
|
|
echo "ERROR: The CUDA SDK version ${NVCC_VERSION} does not support GPUs with a"
|
|
echo " CUDA SM code larger than 90 (found ${CUDA_SM_CODE})"
|
|
echo ""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
if ((NVCC_VERSION > 129)) && ((CUDA_SM_CODE < 75)); then
|
|
echo ""
|
|
echo "ERROR: The CUDA SDK version ${NVCC_VERSION} does not support GPUs with a"
|
|
echo " CUDA SM code smaller than 75 (found ${CUDA_SM_CODE})"
|
|
echo ""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
CMAKE_CUDA_FLAGS="-DCP2K_USE_ACCEL=CUDA"
|
|
CMAKE_CUDA_FLAGS+=" -DCP2K_WITH_GPU=${GPU_MODEL}"
|
|
CMAKE_CUDA_FLAGS+=" -DCMAKE_CUDA_ARCHITECTURES=${CUDA_SM_CODE}"
|
|
CMAKE_CUDA_FLAGS+=" ${CMAKE_FEATURE_FLAGS_GPU}"
|
|
out=()
|
|
for flag in ${CMAKE_CUDA_FLAGS}; do
|
|
[[ ${seen[${flag}]+_} ]] || {
|
|
seen[${flag}]=1
|
|
out+=("${flag}")
|
|
}
|
|
done
|
|
CMAKE_CUDA_FLAGS="$(printf '%s\n' "${out[*]}")"
|
|
echo -e "\nCMAKE_CUDA_FLAGS = ${CMAKE_CUDA_FLAGS}"
|
|
[[ -n "${CUDA_VERSION:-}" ]] && echo -e "\nCUDA_VERSION = ${CUDA_VERSION} (nvcc compiler)"
|
|
[[ -n "${CUDA_HOME:-}" ]] && echo -e "\nCUDA_HOME = ${CUDA_HOME}"
|
|
echo ""
|
|
else
|
|
CMAKE_CUDA_FLAGS="-DCP2K_USE_ACCEL=OFF"
|
|
fi
|
|
export CMAKE_CUDA_FLAGS
|
|
|
|
# Retrieve and print available resources
|
|
free -h
|
|
echo ""
|
|
ulimit -c 0 -s unlimited
|
|
ulimit -a
|
|
echo ""
|
|
|
|
### Build CP2K dependencies with Spack if needed or requested ###
|
|
|
|
# Spack version
|
|
export SPACK_VERSION="${SPACK_VERSION:-1.2.1}"
|
|
export SPACK_BUILD_PATH="${BUILD_PATH}/spack"
|
|
export SPACK_ROOT="${SPACK_BUILD_PATH}/spack"
|
|
|
|
# Isolate user configuration for spack
|
|
export SPACK_DISABLE_LOCAL_CONFIG=true
|
|
export SPACK_USER_CONFIG_PATH="${SPACK_BUILD_PATH}"
|
|
export SPACK_USER_CACHE_PATH="${SPACK_BUILD_PATH}/cache"
|
|
|
|
# Define the CP2K spack configuration file
|
|
export CP2K_CONFIG_FILE="${SPACK_BUILD_PATH}/cp2k_deps_${CP2K_VERSION:0:1}${CP2K_VERSION:4}.yaml"
|
|
|
|
# If requested, remove the spack folder for (re)building all CP2K dependencies
|
|
if [[ "${BUILD_DEPS}" == "always" ]]; then
|
|
for folder in ${SPACK_BUILD_PATH} ${BUILD_PATH}/build ${INSTALL_PREFIX}; do
|
|
if [[ -d "${folder}" ]]; then
|
|
echo "Removing folder \"${folder}\""
|
|
rm -rf "${folder}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# If requested, remove the build folder for (re)building CP2K
|
|
if [[ "${REBUILD_CP2K}" == "yes" ]]; then
|
|
for folder in ${BUILD_PATH}/build ${INSTALL_PREFIX}; do
|
|
if [[ -d "${folder}" ]]; then
|
|
echo "Removing folder \"${folder}\""
|
|
rm -rf "${folder}"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# An incomplete build already contains the Spack installation, source cache,
|
|
# environment, and every successfully installed dependency. Re-enter the
|
|
# setup/install path until the completion marker is written.
|
|
if [[ ! -f "${SPACK_BUILD_PATH}/BUILD_DEPENDENCIES_COMPLETED" ]]; then
|
|
|
|
if [[ -d "${SPACK_BUILD_PATH}" ]]; then
|
|
echo "INFO: Resuming incomplete CP2K dependency build in ${SPACK_BUILD_PATH}"
|
|
else
|
|
echo "INFO: Creating local Spack build directory ${SPACK_BUILD_PATH}"
|
|
fi
|
|
mkdir -p "${SPACK_BUILD_PATH}"
|
|
cd "${SPACK_BUILD_PATH}" || ${EXIT_CMD} 1
|
|
|
|
# Reset the spack environment
|
|
unset SPACK_ENV
|
|
|
|
# Install Spack only when the local bootstrap is absent. wget --continue
|
|
# also retains a partially downloaded release archive across interruptions.
|
|
if [[ ! -d "${SPACK_ROOT}" ]]; then
|
|
echo "Installing Spack ${SPACK_VERSION}"
|
|
if ! wget -q -c "https://github.com/spack/spack/archive/v${SPACK_VERSION}.tar.gz"; then
|
|
echo "ERROR: Downloading Spack ${SPACK_VERSION} failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
if ! tar -xzf "v${SPACK_VERSION}.tar.gz"; then
|
|
echo "ERROR: Extracting Spack ${SPACK_VERSION} failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
if ! mv -f "${SPACK_BUILD_PATH}/spack-${SPACK_VERSION}" "${SPACK_ROOT}"; then
|
|
echo "ERROR: Installing Spack ${SPACK_VERSION} failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
rm -f "v${SPACK_VERSION}.tar.gz"
|
|
fi
|
|
export PATH="${SPACK_ROOT}/bin:${PATH}"
|
|
|
|
# Create cache folder for user configuration
|
|
mkdir -p "${SPACK_USER_CACHE_PATH}"
|
|
|
|
# Set Spack cache (folder is the default)
|
|
export SPACK_CACHE="${SPACK_CACHE:-file://${CP2K_ROOT}/spack_cache}"
|
|
|
|
# Prepare for package caching
|
|
if [[ "${USE_CACHE}" == @("folder"|"minio") ]]; then
|
|
# Create the venv only once, then reuse it on a resumed dependency build.
|
|
if [[ ! -x "${SPACK_BUILD_PATH}/venv/bin/python3" ]]; then
|
|
if command -v python3 -m venv --help &> /dev/null; then
|
|
echo "Installing virtual environment for Python packages"
|
|
if ! python3 -m venv "${SPACK_BUILD_PATH}/venv"; then
|
|
echo "ERROR: The creation of a virtual environment (venv) for Python packages failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
else
|
|
echo "ERROR: python3 -m venv was not found"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
fi
|
|
export PATH="${SPACK_BUILD_PATH}/venv/bin:${PATH}"
|
|
|
|
# Avoid contacting PyPI again when the previously prepared venv is intact.
|
|
if ! python3 -c 'from importlib.metadata import version; assert version("boto3") == "1.38.11"; assert version("google-cloud-storage") == "3.1.0"' &> /dev/null; then
|
|
if ! python3 -m pip --version &> /dev/null; then
|
|
echo "ERROR: python3 -m pip was not found"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
if ! python3 -m pip install "${VERBOSE_FLAG}" --upgrade pip \
|
|
boto3==1.38.11 google-cloud-storage==3.1.0; then
|
|
echo "ERROR: The installation of Python packages for the Spack cache failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Prepare for using an MinIO object storage as cache
|
|
if [[ "${USE_CACHE}" == "minio" ]]; then
|
|
if [[ "${IN_CONTAINER}" == "yes" ]]; then
|
|
echo "ERROR: An external MinIO object storage container cannot be used as cache within a container"
|
|
echo " Use \"folder\" or \"no\" caching instead of \"MinIO\""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
# MinIO requires podman
|
|
if command -v podman &> /dev/null; then
|
|
# Check podman version
|
|
((VERBOSE > 0)) && podman version
|
|
PODMAN_VERSION=$(podman version --format '{{.Client.Version}}' | awk -F'[.-]' '{print $1}')
|
|
if ((PODMAN_VERSION < 4)); then
|
|
echo "WARNING: Outdated podman version $(podman version --format '{{.Client.Version}}') found"
|
|
fi
|
|
export SPACK_CACHE="${SPACK_CACHE:-s3://spack-cache --s3-endpoint-url=http://localhost:9000}"
|
|
if ! "${CP2K_ROOT}"/tools/docker/spack_cache_start.sh; then
|
|
echo "ERROR: Could not start (new) spack cache"
|
|
echo ""
|
|
echo "An error message starting with \"Error: initial journal cursor: ...\" indicates that the"
|
|
echo "journald logging does not work. Try to switch podman (3.x) to file-based logs by creating"
|
|
echo "the file \"~/.config/containers/containers.conf\" with the following two lines:"
|
|
echo "[containers]"
|
|
echo "log_driver = \"k8s-file\""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
else
|
|
echo "INFO: podman was not found"
|
|
echo " Install the package podman to use an MinIO object storage as cache"
|
|
echo " This accelerates a rebuild of the CP2K dependencies, significantly"
|
|
echo " The folder ${SPACK_CACHE} will be used as cache"
|
|
USE_CACHE="folder"
|
|
fi
|
|
fi
|
|
|
|
# Initialize Spack shell hooks
|
|
# shellcheck source=/dev/null
|
|
source "${SPACK_ROOT}/share/spack/setup-env.sh"
|
|
|
|
# Add spack cache as mirror if possible
|
|
if [[ "${USE_CACHE}" == @("folder"|"minio") ]]; then
|
|
echo "SPACK_CACHE = \"${SPACK_CACHE}\""
|
|
spack mirror list
|
|
if ! spack mirror list | grep -q "local-cache"; then
|
|
echo "Setting up spack cache"
|
|
if ((VERBOSE > 0)); then
|
|
"${CP2K_ROOT}"/tools/docker/scripts/setup_spack_cache.sh
|
|
else
|
|
"${CP2K_ROOT}"/tools/docker/scripts/setup_spack_cache.sh &> /dev/null
|
|
fi
|
|
fi
|
|
else
|
|
echo "INFO: A spack cache is NOT used"
|
|
fi
|
|
|
|
# Prepare the CP2K spack configuration file
|
|
CP2K_DEPS_FILE="${CP2K_ROOT}/tools/spack/cp2k_deps_${CP2K_VERSION:0:1}${CP2K_VERSION:4}.yaml"
|
|
if [[ -f "${CP2K_DEPS_FILE}" ]]; then
|
|
sed -E \
|
|
-e "s|root: /opt/spack|root: ${SPACK_ROOT}/opt/spack|" \
|
|
-e "/\"build_type=/s|build_type=[^\"]*|build_type=${DEPS_BUILD_TYPE}|" \
|
|
"${CP2K_DEPS_FILE}" > "${CP2K_CONFIG_FILE}"
|
|
else
|
|
echo -e "\nERROR: The spack configuration file ${CP2K_DEPS_FILE} was not found\n"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Apply selected MPI type if needed
|
|
# MPICH is selected by default for psmp and no change needed for ssmp
|
|
if [[ "${MPI_MODE}" == "openmpi" ]]; then
|
|
sed -E \
|
|
-e '/\s*-\s+"mpich@/ s/^ /#/' \
|
|
-e '/\s*#\s*-\s+"openmpi@/ s/#/ /' \
|
|
-e '/\s*-\s+mpich/ s/mpich$/openmpi/' \
|
|
-i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
|
|
# Activate CUDA in the spack configuration file if requested
|
|
if ((CUDA_SM_CODE > 0)); then
|
|
sed -E \
|
|
-e "0,/~cuda/s//+cuda cuda_arch=${CUDA_SM_CODE}/" \
|
|
-e 's/"~cuda\s+~gpu_direct"/"\+cuda \+gpu_direct"/' \
|
|
-e '/\s*#\s*-\s+"fabrics=efa,ucx"/ s/#/ /' \
|
|
-e '/\s*#\s*-\s+"libxstream@/ s/#/ /' \
|
|
-i "${CP2K_CONFIG_FILE}"
|
|
# Building libfabric with CUDA causes problems
|
|
# sed -E -e 's/"~cuda\s+~gdrcopy"/"\+cuda \+gdrcopy"/' -i "${CP2K_CONFIG_FILE}"
|
|
sed -E -e 's/"~cuda\s+~gdrcopy"/"\~cuda"/' -i "${CP2K_CONFIG_FILE}"
|
|
if [[ -n "${CUDA_VERSION:-}" ]]; then
|
|
# Set CUDA SM code
|
|
sed -E -e "s/spec:\s+cuda@[.0-9]*/spec: cuda@${CUDA_VERSION}/" -i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
if [[ -n "${CUDA_HOME:-}" ]]; then
|
|
sed -E -e "s|prefix: /usr/local/cuda|prefix: ${CUDA_HOME}|" -i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
else
|
|
sed -E -e 's/"~cuda\s+~gdrcopy"/"\~cuda"/' -i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
|
|
# CUDA is required for libgint is requested
|
|
if [[ "${CMAKE_CUDA_FLAGS}" == *"-DCP2K_USE_ACCEL=CUDA"* ]]; then
|
|
if [[ "${CMAKE_FEATURE_FLAGS}" == *"-DCP2K_USE_EVERYTHING=ON"* ]] ||
|
|
[[ "${CMAKE_FEATURE_FLAGS}" == *"-DCP2K_USE_LIBGINT=ON"* ]]; then
|
|
sed -E \
|
|
-e '/\s*#\s*-\s+"libgint@/ s/#/ /' \
|
|
-i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
fi
|
|
|
|
# Activate OpenCL support if requested
|
|
if [[ "${USE_OPENCL}" == "yes" ]]; then
|
|
sed -E \
|
|
-e 's/"~opencl"/"+opencl"/' \
|
|
-e '/\s*#\s*-\s+"libxstream@/ s/#/ /' \
|
|
-i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
|
|
# Apply Cray specific adaptation of the spack configuration if requested (CSCS)
|
|
if [[ "${CRAY}" == "yes" ]]; then
|
|
sed -E \
|
|
-e '/\s*#\s*-\s+"netmod=ofi"/ s/#/ /' \
|
|
-e 's/~xpmem/+xpmem/' \
|
|
-e 's/"libfabric@[.0-9]*"/"libfabric@1.22.0"/' \
|
|
-i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
|
|
# Apply feature selection to spack configuration file
|
|
if [[ -n "${SED_PATTERN_LIST}" ]]; then
|
|
eval sed -E "${SED_PATTERN_LIST}" -i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
|
|
# Find all compilers
|
|
echo "Searching for GCC compilers"
|
|
if ! spack compiler find &> /dev/null; then
|
|
echo "ERROR: The compiler detection of spack failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
spack compiler list
|
|
|
|
# Retrieve the newest compiler version found by spack
|
|
GCC_VERSION_NEWEST="$(spack compilers | sed -nE 's/.*gcc@([0-9]+(\.[0-9]+)*).*/\1/p' | sort -V | tail -n 1)"
|
|
echo "The newest GCC compiler version found by spack is ${GCC_VERSION_NEWEST}"
|
|
GCC_VERSION_NEWEST="$(echo "${GCC_VERSION_NEWEST}" | sed -E -e 's/.*@([0-9]+).*/\1/' | cut -d. -f1)"
|
|
|
|
# Check if the newest compiler version found on the host system is new enough
|
|
GCC_VERSION_MINIMUM="10"
|
|
if ((GCC_VERSION_NEWEST < GCC_VERSION_MINIMUM)); then
|
|
echo "INFO: The newest GCC compiler version ${GCC_VERSION_NEWEST} is too old,"
|
|
echo " because at least version ${GCC_VERSION_MINIMUM} is required"
|
|
GCC_VERSION="14"
|
|
echo "INFO: The lastest stable GCC version ${GCC_VERSION} will be built and used by spack"
|
|
fi
|
|
|
|
# Add a specific GCC version to the spack configuration if requested
|
|
if [[ "${GCC_VERSION}" == "auto" ]]; then
|
|
echo "Spack will automatically select the GCC version which is not necessarily the newest one found"
|
|
else
|
|
sed -E -e "s/gcc@10:/gcc@${GCC_VERSION}/" -i "${CP2K_CONFIG_FILE}"
|
|
fi
|
|
|
|
# Disable PEXSI because of an issue with SuperLU using GCC version 15
|
|
if ((CUDA_SM_CODE > 0)) || ((GCC_VERSION_NEWEST > 14)); then
|
|
sed -E -e '/\s*-\s+"pexsi@/ s/^ /#/' -i "${CP2K_CONFIG_FILE}"
|
|
echo "INFO: PEXSI has been disabled because CUDA or GCC 15 is used"
|
|
fi
|
|
|
|
# Create CP2K environment if needed
|
|
if spack env list | grep -q "${CP2K_ENV}"; then
|
|
echo "The Spack environment \"${CP2K_ENV}\" exists already"
|
|
else
|
|
cat "${CP2K_CONFIG_FILE}"
|
|
echo "The Spack environment \"${CP2K_ENV}\" does NOT exist"
|
|
if spack env create "${CP2K_ENV}" "${CP2K_CONFIG_FILE}" &> /dev/null; then
|
|
echo "The Spack environment \"${CP2K_ENV}\" has been created"
|
|
else
|
|
echo "ERROR: The creation of the Spack environment \"${CP2K_ENV}\" failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
fi
|
|
|
|
# Activate CP2K environment if needed
|
|
if spack env activate "${CP2K_ENV}" &> /dev/null; then
|
|
echo "The Spack environment \"${CP2K_ENV}\" has been activated"
|
|
else
|
|
echo "ERROR: The activation of the Spack environment \"${CP2K_ENV}\" failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Update the repo builtin
|
|
if ! spack repo update; then
|
|
echo "ERROR: The update of the repo builtin failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Add the local CP2K development Spack repository when missing
|
|
export CP2K_REPO="cp2k_dev"
|
|
if ! spack repo list | grep -q "${CP2K_REPO}"; then
|
|
spack repo add --scope "env:${CP2K_ENV}" "${CP2K_ROOT}/tools/spack/spack_repo/${CP2K_REPO}"
|
|
else
|
|
echo "The CP2K development repo ${CP2K_REPO} is already present ... skipping add"
|
|
fi
|
|
|
|
spack -e ${CP2K_ENV} repo list
|
|
|
|
# Find all external packages
|
|
if [[ "${USE_EXTERNALS}" == "yes" ]]; then
|
|
if ! spack -C "${SPACK_USER_CONFIG_PATH}" external find; then
|
|
echo -e "\nERROR: The detection of externals by spack failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
# Concretize CP2K dependencies
|
|
if ! spack -e "${CP2K_ENV}" concretize --fresh --jobs "${NUM_PROCS}"; then
|
|
echo -e "\nERROR: The spack concretize for environment \"${CP2K_ENV}\" failed"
|
|
echo ""
|
|
echo "HINT: The (-ue | --use_externals) flags can cause conflicts with outdated"
|
|
echo " packages on the host system, e.g. old python or gcc versions"
|
|
echo ""
|
|
${EXIT_CMD} 1
|
|
fi
|
|
else
|
|
# If the installation of a specific GCC version for building CP2K is requested,
|
|
# then an installation of the same GCC version on the host system has to be removed
|
|
# from the configuration for a static build of CP2K
|
|
if [[ "${CP2K_VERSION}" == *"-static" ]]; then
|
|
if spack compilers | grep -q "gcc@${GCC_VERSION}"; then
|
|
echo "INFO: A static build of CP2K with GCC ${GCC_VERSION} is requested without using"
|
|
echo " any externals which requires to build that GCC version with spack"
|
|
echo " while removing a gcc@${GCC_VERSION} installed on the host from the spack"
|
|
echo " configuration at the same time"
|
|
if ! spack compiler remove "gcc@${GCC_VERSION}"; then
|
|
echo -e "\nERROR: Removing the gcc@${GCC_VERSION} compiler failed"
|
|
${EXIT_CMD} 1
|
|
else
|
|
echo -e "\nINFO: gcc@${GCC_VERSION} compiler removed"
|
|
fi
|
|
spack compiler list
|
|
fi
|
|
fi
|
|
if ! spack -e "${CP2K_ENV}" concretize --fresh --jobs "${NUM_PROCS}"; then
|
|
echo -e "\nERROR: The spack concretize for environment \"${CP2K_ENV}\" failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
fi
|
|
|
|
((VERBOSE > 0)) && spack find -c
|
|
|
|
# Install CP2K dependencies via Spack
|
|
if ! spack -e "${CP2K_ENV}" install -j "${NUM_PROCS}" -p "${NUM_PACKAGES}" "${VERBOSE_SPACK}"; then
|
|
echo "ERROR: Building the CP2K dependencies with spack failed"
|
|
if [[ "${USE_EXTERNALS}" == "yes" ]]; then
|
|
echo "HINT: Try to re-run the build without the (-ue | --use_externals) flag which avoids"
|
|
echo " errors or conflicts caused by externals from the host system"
|
|
fi
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Find all compilers
|
|
if ! spack compiler find; then
|
|
echo "ERROR: The compiler detection of spack failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Fix Libs list in elpa pkg-config file when CUDA is used
|
|
if ((CUDA_SM_CODE > 0)); then
|
|
ELPA_PKG_CONFIG_FILE="$(find -L "${SPACK_ROOT}/opt/spack/view" -name "elpa*.pc")"
|
|
if [[ -f "${ELPA_PKG_CONFIG_FILE}" ]]; then
|
|
sed -E -e 's|Libs: |Libs: -L/usr/local/cuda/lib64 |' -i "${ELPA_PKG_CONFIG_FILE}"
|
|
fi
|
|
fi
|
|
|
|
# Return from spack folder after all installations are done
|
|
cd "${CP2K_ROOT}" || ${EXIT_CMD} 1
|
|
|
|
# Make a note of the successful build
|
|
touch "${SPACK_BUILD_PATH}/BUILD_DEPENDENCIES_COMPLETED"
|
|
|
|
echo -e '\n*** Installation of CP2K dependencies completed ***\n'
|
|
|
|
else
|
|
|
|
# Initialize Spack shell hooks
|
|
# shellcheck source=/dev/null
|
|
source "${SPACK_ROOT}"/share/spack/setup-env.sh
|
|
|
|
fi
|
|
|
|
# Quit after (re)building all CP2K dependencies if requested
|
|
if [[ "${BUILD_DEPS_ONLY}" == "yes" ]]; then
|
|
${EXIT_CMD}
|
|
fi
|
|
|
|
### End of build CP2K dependencies ###
|
|
|
|
### Build CP2K ###
|
|
|
|
if spack env list | grep -q "${CP2K_ENV}"; then
|
|
spack env list
|
|
else
|
|
echo "ERROR: No Spack environment \"${CP2K_ENV}\" found"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
|
|
# Activate spack environment
|
|
eval "$(spack env activate --sh ${CP2K_ENV})"
|
|
|
|
spack env status
|
|
|
|
# CMake configuration step
|
|
export CMAKE_BUILD_PATH="${BUILD_PATH}/build"
|
|
|
|
# PyTorch's TorchConfig.cmake is buried in the Python site-packages directory
|
|
Torch_DIR="$(dirname "$(find "${SPACK_ROOT}" ! -type l -name TorchConfig.cmake | tail -n 1)")"
|
|
export Torch_DIR
|
|
|
|
# Check if PEXSI was built
|
|
if [[ "${MPI_MODE}" != "no" ]]; then
|
|
CP2K_USE_PEXSI="$(grep -Eq '\s*#\s*-\s+"pexsi@' "${CP2K_CONFIG_FILE}" && echo OFF || echo ON)"
|
|
else
|
|
CP2K_USE_PEXSI="ON"
|
|
fi
|
|
export CP2K_USE_PEXSI
|
|
|
|
if [[ ! -d "${CMAKE_BUILD_PATH}" ]]; then
|
|
mkdir -p "${CMAKE_BUILD_PATH}"
|
|
case "${CP2K_VERSION}" in
|
|
pdbg | psmp)
|
|
# shellcheck disable=SC2086
|
|
cmake -S "${CP2K_ROOT}" -B "${CMAKE_BUILD_PATH}" \
|
|
-GNinja \
|
|
-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} \
|
|
-DCMAKE_BUILD_TYPE="${CP2K_BUILD_TYPE}" \
|
|
-DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \
|
|
-DCMAKE_INSTALL_MESSAGE="${INSTALL_MESSAGE}" \
|
|
-DCMAKE_SKIP_RPATH="ON" \
|
|
-DCMAKE_VERBOSE_MAKEFILE="${VERBOSE_MAKEFILE}" \
|
|
${CMAKE_FEATURE_FLAGS} \
|
|
-DCP2K_USE_PEXSI="${CP2K_USE_PEXSI}" \
|
|
${CMAKE_CUDA_FLAGS} \
|
|
-Werror=dev |&
|
|
tee "${CMAKE_BUILD_PATH}/cmake.log"
|
|
EXIT_CODE=$?
|
|
;;
|
|
sdbg | ssmp)
|
|
# shellcheck disable=SC2086
|
|
cmake -S "${CP2K_ROOT}" -B "${CMAKE_BUILD_PATH}" \
|
|
-GNinja \
|
|
-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} \
|
|
-DCMAKE_BUILD_TYPE="${CP2K_BUILD_TYPE}" \
|
|
-DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \
|
|
-DCMAKE_INSTALL_MESSAGE="${INSTALL_MESSAGE}" \
|
|
-DCMAKE_SKIP_RPATH="ON" \
|
|
-DCMAKE_VERBOSE_MAKEFILE="${VERBOSE_MAKEFILE}" \
|
|
${CMAKE_FEATURE_FLAGS} \
|
|
${CMAKE_CUDA_FLAGS} \
|
|
-Werror=dev |&
|
|
tee "${CMAKE_BUILD_PATH}/cmake.log"
|
|
EXIT_CODE=$?
|
|
;;
|
|
ssmp-static)
|
|
# Find some static libraries in advance
|
|
LIBOPENBLAS=$(find -L "${SPACK_ROOT}"/opt/spack/view -name libopenblas.a)
|
|
LIBM="$(find /usr -name libm.a 2> /dev/null)"
|
|
# shellcheck disable=SC2086
|
|
cmake -S "${CP2K_ROOT}" -B "${CMAKE_BUILD_PATH}" \
|
|
-GNinja \
|
|
-DBUILD_SHARED_LIBS="OFF" \
|
|
-DCMAKE_BUILD_TYPE="${CP2K_BUILD_TYPE}" \
|
|
-DCMAKE_EXE_LINKER_FLAGS="-static" \
|
|
-DCMAKE_FIND_LIBRARY_SUFFIXES=".a" \
|
|
-DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \
|
|
-DCMAKE_INSTALL_MESSAGE="${INSTALL_MESSAGE}" \
|
|
-DCMAKE_SKIP_RPATH="ON" \
|
|
-DCMAKE_VERBOSE_MAKEFILE="${VERBOSE_MAKEFILE}" \
|
|
-DCP2K_BLAS_LINK_LIBRARIES="${LIBOPENBLAS};${LIBM}" \
|
|
-DCP2K_LAPACK_LINK_LIBRARIES="${LIBOPENBLAS};${LIBM}" \
|
|
${CMAKE_FEATURE_FLAGS} \
|
|
-Werror=dev |&
|
|
tee "${CMAKE_BUILD_PATH}/cmake.log"
|
|
EXIT_CODE=$?
|
|
# It is almost impossible to avoid that shared libraries are pulled in
|
|
# when the CP2K dependencies are built and thus just change all shared
|
|
# to static libraries hoping that these are also available
|
|
sed -E -e "s/\.so/.a/g" -i build/build.ninja
|
|
;;
|
|
*)
|
|
echo "ERROR: Unknown CP2K version ${CP2K_VERSION} specified"
|
|
${EXIT_CMD} 1
|
|
;;
|
|
esac
|
|
if ((EXIT_CODE != 0)); then
|
|
echo "ERROR: The CMake configuration step failed with the error code ${EXIT_CODE}"
|
|
echo " You can try to remove the build folder with 'rm -rf build' and re-run"
|
|
echo " or even start the whole CP2K installation from scratch with the \"-bd\" flag"
|
|
${EXIT_CMD} "${EXIT_CODE}"
|
|
fi
|
|
fi
|
|
|
|
# CMake build step
|
|
echo -e '\n*** Compiling CP2K ***\n'
|
|
cmake --build "${CMAKE_BUILD_PATH}" --parallel "${NUM_PROCS}" -- "${VERBOSE_FLAG}" |& tee "${CMAKE_BUILD_PATH}"/ninja.log
|
|
EXIT_CODE=${PIPESTATUS[0]}
|
|
if ((EXIT_CODE != 0)); then
|
|
echo "ERROR: The CMake build step failed with the error code ${EXIT_CODE}"
|
|
${EXIT_CMD} "${EXIT_CODE}"
|
|
fi
|
|
|
|
# CMake install step
|
|
echo -e '\n*** Installing CP2K ***\n'
|
|
cmake --install "${CMAKE_BUILD_PATH}" |& tee "${CMAKE_BUILD_PATH}"/install.log
|
|
EXIT_CODE=${PIPESTATUS[0]}
|
|
if ((EXIT_CODE != 0)); then
|
|
echo -e "\nERROR: The CMake installation step failed with the error code ${EXIT_CODE}"
|
|
${EXIT_CMD} "${EXIT_CODE}"
|
|
fi
|
|
|
|
# Install Skala resource files if needed
|
|
export GAUXC_SKALA_MODEL="(not available)"
|
|
if spack location -i gauxc &> /dev/null; then
|
|
GAUXC_PATH="share/gauxc/onedft_models"
|
|
GAUXC_PREFIX="$(spack location -i gauxc)"
|
|
GAUXC_MODEL_SOURCE_PATH="${GAUXC_PREFIX%/}/${GAUXC_PATH}"
|
|
if [[ -d "${GAUXC_MODEL_SOURCE_PATH}" ]]; then
|
|
GAUXC_MODEL_TARGET_PATH="${INSTALL_PREFIX%/}/${GAUXC_PATH}"
|
|
mkdir -p "${GAUXC_MODEL_TARGET_PATH}"
|
|
if compgen -G "${GAUXC_MODEL_SOURCE_PATH}/*.fun" > /dev/null; then
|
|
cp "${GAUXC_MODEL_SOURCE_PATH}"/*.fun "${GAUXC_MODEL_TARGET_PATH}/"
|
|
else
|
|
echo -e "\nERROR: No GauXC model files found in source folder ${GAUXC_MODEL_SOURCE_PATH}"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
shopt -s nullglob
|
|
MATCHES=("${GAUXC_MODEL_TARGET_PATH}"/skala*)
|
|
shopt -u nullglob
|
|
if ((${#MATCHES[@]} > 0)); then
|
|
export GAUXC_SKALA_MODEL="${MATCHES[${#MATCHES[@]} - 1]}"
|
|
else
|
|
echo -e "\nERROR: Failed to resolve GAUXC_SKALA_MODEL in target path ${GAUXC_MODEL_TARGET_PATH}"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
fi
|
|
fi
|
|
echo -e "\nGAUXC_SKALA_MODEL = ${GAUXC_SKALA_MODEL}"
|
|
|
|
# Collect and compress all log files when building within a container
|
|
if [[ "${IN_CONTAINER}" == "yes" ]]; then
|
|
if ! cat "${CMAKE_BUILD_PATH}"/cmake.log \
|
|
"${CMAKE_BUILD_PATH}"/ninja.log \
|
|
"${CMAKE_BUILD_PATH}"/install.log |
|
|
gzip > "${CP2K_ROOT}"/install/build_cp2k.log.gz; then
|
|
echo -e "\nERROR: The compressed log file generation failed"
|
|
${EXIT_CMD} 1
|
|
fi
|
|
fi
|
|
|
|
# Cut extension from the CP2K version (e.g. ssmp-static -> ssmp)
|
|
export VERSION=${CP2K_VERSION%%-*}
|
|
|
|
# Add CP2K lib folder to the LD_LIBRARY_PATH
|
|
export LD_LIBRARY_PATH="${INSTALL_PREFIX}/lib:${LD_LIBRARY_PATH}"
|
|
|
|
# Assemble search paths for libraries
|
|
search_paths="${SPACK_ROOT}/opt/spack/view ${INSTALL_PREFIX}/lib"
|
|
|
|
# Retrieve paths to all libraries needed by the CP2k binary
|
|
for library in $(readelf -d "${INSTALL_PREFIX}/bin/cp2k.${VERSION}" "${INSTALL_PREFIX}"/lib/libcp2k.* | awk '/NEEDED/{print $5}' | tr -d '[]' | sort | uniq); do
|
|
# Search for missing library path
|
|
if ! ldconfig -p | grep -qE "/${library}$"; then
|
|
# shellcheck disable=SC2086
|
|
library_with_path=$(find -L ${search_paths} -name "${library}" | tail -n 1)
|
|
if [[ -n "${library_with_path}" ]]; then
|
|
library_path="$(dirname "${library_with_path}")"
|
|
case ":${LD_LIBRARY_PATH}:" in
|
|
*":${library_path}:"*)
|
|
((VERBOSE > 1)) && echo "The library path ${library_path} is already present ... skipping"
|
|
;;
|
|
*)
|
|
LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+${LD_LIBRARY_PATH}:}${library_path}"
|
|
((VERBOSE > 0)) && echo "The library path ${library_path} was appended to LD_LIBRARY_PATH"
|
|
;;
|
|
esac
|
|
fi
|
|
fi
|
|
done
|
|
export LD_LIBRARY_PATH
|
|
echo -e "\nLD_LIBRARY_PATH = \"${LD_LIBRARY_PATH}\""
|
|
|
|
# Create an ld configuration file for CP2K because LD_LIBRARY_PATH is fragile
|
|
if [[ "${IN_CONTAINER}" == "yes" ]]; then
|
|
CP2K_LD_CONF_FILE="/etc/ld.so.conf.d/cp2k.conf"
|
|
else
|
|
CP2K_LD_CONF_FILE="${INSTALL_PREFIX}/bin/cp2k.conf"
|
|
fi
|
|
|
|
# Either read LD_LIBRARY_PATH from an existing configuration file or write a new one
|
|
if [[ -f "${CP2K_LD_CONF_FILE}" ]]; then
|
|
# Load LD_LIBRARY_PATH from an existing configuration file
|
|
LD_LIBRARY_PATH="$(grep -E '^/' "${CP2K_LD_CONF_FILE}" | paste -sd ':' -)"
|
|
else
|
|
# Write LD_LIBRARY_PATH to a new configuration file
|
|
echo "${LD_LIBRARY_PATH}" | tr ':' '\n' | grep '^/' > "${CP2K_LD_CONF_FILE}"
|
|
fi
|
|
|
|
export LD_LIBRARY_PATH
|
|
|
|
# Create links to CP2K binaries
|
|
cd "${INSTALL_PREFIX}"/bin || ${EXIT_CMD} 1
|
|
for binary in *."${VERSION}"; do
|
|
if ! ln -sf "${binary}" "${binary%%."${VERSION}"}"; then
|
|
echo "ERROR: The creation of a symbolic link for the binary ${binary} failed"
|
|
${EXIT_CMD}
|
|
fi
|
|
done
|
|
ln -sf cp2k."${VERSION}" cp2k_shell
|
|
cd "${CP2K_ROOT}" || ${EXIT_CMD} 1
|
|
|
|
# Configure Open MPI environment for local CP2K runs
|
|
if [[ "${MPI_MODE}" == "openmpi" ]]; then
|
|
OMPI_VARS="export OMPI_MCA_plm_rsh_agent=/bin/false PRTE_MCA_hwloc_default_binding_policy=none"
|
|
if [[ "${IN_CONTAINER}" == "yes" ]]; then
|
|
OMPI_VARS="${OMPI_VARS} OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1"
|
|
OMPI_VARS="${OMPI_VARS} OMPI_MCA_mpi_yield_when_idle=1 OMPI_MCA_btl=self,sm OMPI_MCA_pml=ob1"
|
|
fi
|
|
else
|
|
OMPI_VARS=""
|
|
fi
|
|
export OMPI_VARS
|
|
|
|
# MPICH and OpenMPI have different flags for exporting environment variables to MPI ranks
|
|
if [[ "${MPI_MODE}" == "openmpi" ]]; then
|
|
ENV_VAR_FLAG="-x"
|
|
else
|
|
ENV_VAR_FLAG="-genv"
|
|
fi
|
|
export ENV_VAR_FLAG
|
|
|
|
# Install LSAN suppressions (only needed for dbg binaries)
|
|
cp "${CP2K_ROOT}"/tools/spack/lsan.supp "${INSTALL_PREFIX}"/bin
|
|
|
|
# Assemble flags for running the regression tests
|
|
TESTOPTS="--cp2kdatadir ${INSTALL_PREFIX}/share/cp2k/data --maxtasks ${NUM_PROCS} --workbasedir ${INSTALL_PREFIX}/regtesting ${TESTOPTS}"
|
|
export TESTOPTS
|
|
|
|
# Create launch script for environment setup
|
|
LAUNCH_SCRIPT="${INSTALL_PREFIX}"/bin/launch
|
|
export LAUNCH_SCRIPT
|
|
cat << *** > "${LAUNCH_SCRIPT}"
|
|
#!/bin/bash
|
|
ulimit -c 0 -s unlimited
|
|
export ASAN_OPTIONS="detect_leaks=1"
|
|
export LSAN_OPTIONS="suppressions=${INSTALL_PREFIX}/bin/lsan.supp"
|
|
export PATH=${INSTALL_PREFIX}/bin:${PATH}
|
|
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
|
|
export OMP_NUM_THREADS=\${OMP_NUM_THREADS:-2}
|
|
export OMP_STACKSIZE=256M
|
|
${OMPI_VARS}
|
|
export GAUXC_SKALA_MODEL=${GAUXC_SKALA_MODEL}
|
|
exec "\$@"
|
|
***
|
|
chmod 750 "${LAUNCH_SCRIPT}"
|
|
|
|
# Create shortcut for launching the regression tests
|
|
cat << *** > "${INSTALL_PREFIX}"/bin/run_tests
|
|
#!/bin/bash
|
|
if [[ "${VERSION}" =~ ^(s|p)dbg$ ]]; then
|
|
echo "ASAN_OPTIONS = \${ASAN_OPTIONS}"
|
|
echo "LSAN_OPTIONS = \${LSAN_OPTIONS}"
|
|
fi
|
|
ldd -- ${INSTALL_PREFIX}/bin/cp2k.${VERSION} 2>&1 | grep -E 'not ' | sort | uniq
|
|
export GAUXC_SKALA_MODEL=${GAUXC_SKALA_MODEL}
|
|
${CP2K_ROOT}/tests/do_regtest.py ${TESTOPTS} \$* ${INSTALL_PREFIX}/bin ${VERSION}
|
|
***
|
|
chmod 750 "${INSTALL_PREFIX}"/bin/run_tests
|
|
|
|
# Set image tag if available
|
|
export IMAGE_TAG=${IMAGE_TAG:-<IMAGE ID>}
|
|
|
|
# Optionally, launch test run
|
|
if [[ "${RUN_TEST}" == "yes" ]]; then
|
|
echo -e "\n*** Launching regression test run using the script ${INSTALL_PREFIX}/bin/run_tests\n"
|
|
${LAUNCH_SCRIPT} run_tests
|
|
EXIT_CODE=$?
|
|
if ((EXIT_CODE != 0)); then
|
|
echo "ERROR: The regression test run failed with the error code ${EXIT_CODE}"
|
|
${EXIT_CMD} "${EXIT_CODE}"
|
|
fi
|
|
else
|
|
if [[ "${IN_CONTAINER}" == "yes" ]]; then
|
|
if ((CUDA_SM_CODE > 0)); then
|
|
DEVICE_FLAG=" --device nvidia.com/gpu=all"
|
|
else
|
|
DEVICE_FLAG=""
|
|
fi
|
|
echo ""
|
|
echo "*** A regression test run can be launched with"
|
|
echo " podman run -it${DEVICE_FLAG} --rm ${IMAGE_TAG} run_tests"
|
|
echo ""
|
|
if [[ "${VERSION}" == @(sdbg|ssmp) ]]; then
|
|
echo "*** A CP2K run using 2 OpenMP threads (default) can be launched with"
|
|
echo " podman run -it${DEVICE_FLAG} --rm ${IMAGE_TAG} cp2k ${CP2K_ROOT}/benchmarks/CI/H2O-32_md.inp"
|
|
else
|
|
echo "*** An MPI-parallel CP2K run using 2 OpenMP threads for each of the 4 MPI ranks can be launched with"
|
|
echo " podman run -it${DEVICE_FLAG} --rm ${IMAGE_TAG} mpiexec -n 4 ${ENV_VAR_FLAG} OMP_NUM_THREADS=2 cp2k ${CP2K_ROOT}/benchmarks/CI/H2O-32_md.inp"
|
|
fi
|
|
echo ""
|
|
else
|
|
echo ""
|
|
echo "*** A regression test run can be launched with"
|
|
echo " ${LAUNCH_SCRIPT} run_tests"
|
|
echo ""
|
|
if [[ "${VERSION}" == @(sdbg|ssmp) ]]; then
|
|
echo "*** A CP2K run using 2 OpenMP threads (default) can be launched with"
|
|
echo " ${LAUNCH_SCRIPT} cp2k ${CP2K_ROOT}/benchmarks/CI/H2O-32_md.inp"
|
|
echo ""
|
|
echo "*** A CP2K run using only 4 OpenMP threads can be launched with"
|
|
echo " export OMP_NUM_THREADS=4; ${LAUNCH_SCRIPT} cp2k ${CP2K_ROOT}/benchmarks/CI/H2O-32_md.inp"
|
|
else
|
|
echo "*** An MPI-parallel CP2K run using 2 OpenMP threads for each of the 4 MPI ranks can be launched with"
|
|
echo " export OMP_NUM_THREADS=2; ${LAUNCH_SCRIPT} mpiexec -n 4 cp2k ${CP2K_ROOT}/benchmarks/CI/H2O-32_md.inp"
|
|
fi
|
|
echo ""
|
|
fi
|
|
fi
|