Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ include(ProjectSetup)
set(IPPL_PLATFORMS "SERIAL" CACHE STRING "Platforms to build IPPL for")
option(BUILD_SHARED_LIBS "Build IPPL as a shared library" OFF)
option(IPPL_ENABLE_UNIT_TESTS "Enable unit tests using GoogleTest" OFF)
option(IPPL_ENABLE_KOKKOS_KERNELS "Enable Kokkos Kernels linear algebra support" OFF)
option(IPPL_ENABLE_FFT "Enable FFT support" OFF)
option(IPPL_ENABLE_CUFFTMP "Enable NVIDIA cuFFTMp FFT backend" OFF)
option(IPPL_ENABLE_FINUFFT "Enable FINUFFT NUFFT backend" OFF)
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ The [IPPL Manual](https://ippl-framework.github.io/Manual/) contains comprehensi

For detailed API, class, and file documentation, please visit our [Doxygen site](https://ippl-framework.github.io/ippl/).

Kokkos Kernels support is optional and can be enabled with
`-DIPPL_ENABLE_KOKKOS_KERNELS=ON`. Missing host LAPACKE is then built from source
using C and Fortran compilers; installed LAPACKE or MKL providers are also supported.
See [Kokkos Kernels configuration](cmake/BuildSystem.md#kokkos-kernels-and-host-eigenanalysis)
for dependency setup and options controlling host eigenanalysis.

**Feedback & Support**
If you find any issues with the manual, please report them in the [Manual's GitHub repository](https://github.com/IPPL-framework/Manual).

Expand Down
13 changes: 13 additions & 0 deletions ci/cscs/dashboard-configure-build.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ set(VARS_TO_FORWARD
IPPL_ENABLE_SCRIPTS
Heffte_VERSION
Kokkos_VERSION
KokkosKernels_VERSION
IPPL_ENABLE_KOKKOS_KERNELS
IPPL_KOKKOS_KERNELS_HOST
IPPL_LAPACK_INTEGER_BYTES
IPPL_FETCH_LAPACKE
IPPL_LAPACKE_BUILD_JOBS
IPPL_LAPACKE_TOOLCHAIN_FILE
CMAKE_Fortran_COMPILER
LAPACKE_ROOT
LAPACKE_INCLUDE_DIRS
LAPACKE_LIBRARY_DIRS
LAPACKE_LIBRARIES
MKL_DIR
MPIEXEC_EXECUTABLE
MPIEXEC_PREFLAGS
MPIEXEC_MAX_NUMPROCS
Expand Down
162 changes: 162 additions & 0 deletions cmake/BuildSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,165 @@ target_link_libraries(app PRIVATE ippl::ippl)
```



## Kokkos Kernels and host eigenanalysis

`IPPL_ENABLE_KOKKOS_KERNELS` defaults to `OFF`. Set it to `ON` to enable this
support. IPPL first finds an installed Kokkos Kernels package (default minimum
version 5.2.0), then falls back to FetchContent.
`KokkosKernels_VERSION=git.<tag-or-sha>` requests a source build. The package uses
the Kokkos target already selected by IPPL. An external package must have been
built against a compatible Kokkos with the required backends.

The following CMake cache variables control this support:

- `IPPL_ENABLE_KOKKOS_KERNELS` (`OFF`): enable Kokkos Kernels and its IPPL unit
test. The remaining variables in this list are used only when this is `ON`.
- `KokkosKernels_VERSION` (`5.2.0`): required package version. Prefix the value
with `git.` to request a specific source tag, branch, or commit.
- `IPPL_KOKKOS_KERNELS_HOST` (`LAPACKE`): select `LAPACKE`, `MKL`, or `NONE` for
host eigenanalysis.
- `IPPL_LAPACK_INTEGER_BYTES` (`4`): select the 4-byte LP64 or 8-byte ILP64
integer interface.
- `IPPL_FETCH_LAPACKE` (`ON`): build reference LAPACK and LAPACKE when the
`LAPACKE` provider cannot be found.
- `IPPL_LAPACKE_BUILD_JOBS` (`4`): parallel jobs for the reference LAPACK build.
This cache entry is created only when the fallback is needed.
- `IPPL_LAPACKE_TOOLCHAIN_FILE` (empty): C/Fortran toolchain used by the fallback,
required when cross-compiling. This entry is also created only when needed.

Installed dependencies can be selected with `KokkosKernels_DIR`, `LAPACKE_ROOT`,
`LAPACKE_INCLUDE_DIRS`, `LAPACKE_LIBRARY_DIRS`, `LAPACKE_LIBRARIES`, or `MKL_DIR`.
`LAPACKE_LIBRARIES` is a semicolon-separated complete link line and may contain
absolute paths, library names, imported targets, and linker items such as `-lm`.
The standard FetchContent overrides `FETCHCONTENT_SOURCE_DIR_KOKKOSKERNELS` and
`FETCHCONTENT_SOURCE_DIR_IPPL_REFERENCE_LAPACK` support offline source trees.
Set `CMAKE_Fortran_COMPILER` or the `FC` environment variable to choose the
fallback Fortran compiler; use `CC` to choose its C compiler.

The minimum opt-in configuration is:

```console
cmake -S . -B build -DIPPL_ENABLE_KOKKOS_KERNELS=ON
```

CUDA and HIP BLAS, sparse, and solver TPLs are selected automatically from
`IPPL_PLATFORMS`; they do not require additional IPPL cache variables.

Host eigenanalysis is selected independently of `IPPL_PLATFORMS`:

- `IPPL_KOKKOS_KERNELS_HOST=LAPACKE` (default): provide LAPACKE headers and a
complete LAPACKE/LAPACK/BLAS link line. Set `LAPACKE_ROOT`, or
`LAPACKE_INCLUDE_DIRS` and `LAPACKE_LIBRARIES`. Static link lines must include
transitive dependencies, such as the Fortran runtime. Library names can be
resolved through `LAPACKE_LIBRARY_DIRS`; absolute paths are supported.
- `IPPL_KOKKOS_KERNELS_HOST=MKL`: provide an MKL CMake package through
`CMAKE_PREFIX_PATH`/`MKL_DIR` (modern oneMKL).
- `IPPL_KOKKOS_KERNELS_HOST=NONE`: use portable/GPU kernels without requesting
host eigenanalysis; only the GEMM regression is registered in the test binary.
- `IPPL_ENABLE_KOKKOS_KERNELS=OFF` (default): omit the dependency and its tests entirely.

Kokkos does not install these external libraries. If host LAPACKE is not found,
IPPL now downloads reference LAPACK 3.12.1 (SHA256-verified) and builds its BLAS,
LAPACK and LAPACKE libraries. The fallback requires host C and Fortran compilers;
Comment thread
aaadelmann marked this conversation as resolved.
set `CMAKE_Fortran_COMPILER` or `FC` if automatic discovery cannot find gfortran.
The host C compiler is selected independently via `CC` or the fallback toolchain.
It supports LP64 and ILP64 through `IPPL_LAPACK_INTEGER_BYTES` and builds static
Comment thread
aaadelmann marked this conversation as resolved.
position-independent libraries for use by shared or static IPPL.

The first configure builds this dependency in an isolated host project under
`_deps`, before the existing compile/link/runtime probes run. This can take a few
minutes; subsequent configures reuse the build. CUDA/HIP compiler launchers and
IPPL's directory flags are not applied to the host project. Its logs are in
`_deps/ippl-host-lapack-<integer-bytes>-build/{configure,build,install}.log`.
`IPPL_LAPACKE_BUILD_JOBS` controls build parallelism (default 4).
Comment thread
aaadelmann marked this conversation as resolved.
For offline builds, point `FETCHCONTENT_SOURCE_DIR_IPPL_REFERENCE_LAPACK` at an
already unpacked reference LAPACK 3.12.1 source tree.

Set `IPPL_FETCH_LAPACKE=OFF` to require an installed provider. An explicit
Comment thread
aaadelmann marked this conversation as resolved.
`LAPACKE_LIBRARIES` remains authoritative: missing headers or broken linkage
produce errors instead of silently substituting a different provider. A Kernels
package already built without its LAPACKE TPL still needs rebuilding; fetching
LAPACKE cannot enable features in an installed Kernels library.

For a cross build, supply `IPPL_LAPACKE_TOOLCHAIN_FILE` with a C/Fortran toolchain
Comment thread
aaadelmann marked this conversation as resolved.
for the target CPU, or use an installed provider. Runtime checks remain deferred
in cross builds. Fetched libraries, headers, license and the relocatable
`IPPLHostLapack` CMake package are bundled with IPPL's installation; the compatible
Fortran compiler runtime remains a system dependency.

On macOS, an installed OpenBLAS build with LAPACKE or reference LAPACK can also be
used. Apple's Accelerate alone does not supply this LAPACKE interface.
Installation paths belong in site presets/toolchain files, not repository CMake.
For example, source builds can use these preset cache entries:

```json
{
"IPPL_ENABLE_KOKKOS_KERNELS": "ON",
"IPPL_KOKKOS_KERNELS_HOST": "LAPACKE",
"LAPACKE_ROOT": "/site/path/to/lapacke",
"IPPL_LAPACK_INTEGER_BYTES": "4"
}
```

Use headers and libraries from one compatible provider. Integer size defaults to
4 bytes (LP64); 8 selects ILP64 and propagates `LAPACK_ILP64` or `MKL_ILP64` to IPPL
consumers. For MKL source builds it also selects `MKL_INTERFACE`. Changing this
option cannot convert an installed library to another ABI. Configure checks the
header integer size, links an actual `LAPACKE_dgeev` call, and, for native builds,
runs a small spectrum/status check. Cross builds defer runtime checks to tests.
These checks are smoke tests, not a substitute for a consistent vendor build.
Providers with renamed symbols (for example, `LAPACKE_dgeev64_`) need matching
headers exposing the standard LAPACKE call; integer-size selection alone does
not adapt symbol names. Incompatible installations are rejected by the link probe.

CUDA source builds enable cuBLAS, cuSOLVER and cuSPARSE. HIP source builds enable
rocBLAS, rocSOLVER and rocSPARSE (the sparse libraries are required by the solver
TPL configuration). Supply `CUDAToolkit_ROOT` or ROCm's `CMAKE_PREFIX_PATH` in site
presets. Host LAPACKE/MKL remains necessary when host eigenanalysis is requested.
Installed Kernels configurations are inspected for the requested TPLs; changing
cache options cannot add a missing TPL to an installed package. All link
requirements propagate through `Kokkos::kokkoskernels` and `IPPL::ippl`.

Source builds default to on-demand kernel instantiation rather than default ETI.
`KokkosKernels_ADD_DEFAULT_ETI=ON` can enable upstream's preinstantiations.
Supernodal SPTRSV defaults off because it requires LayoutLeft ETI; applications
needing it should configure the required ETI and enable it explicitly.

The `KokkosKernelsLinearMap` unit test constructs coupled 4x4 maps using GEMM in
the default execution/memory space, explicitly copies results to host memory,
and verifies analytical eigenvalues and normalized right-eigenvector residuals.
It covers stable rotations, conjugate branches, coupled modes, real/complex
instabilities, and near-integer/neutral modes. Eigenvalue/residual tolerance is
1e-12 for small, well-conditioned double-precision maps; GEMM tolerance is 1e-14.
No production physics algorithm or reduction ordering is changed.

The test calls the configured host `LAPACKE_dgeev` directly with column-major
Kokkos host views. Kokkos Kernels 5.2.0's experimental `SerialEigendecomposition`
header contains an invalid Householder template call rejected by GCC 15 and
Clang 21; its
device implementation is unfinished and its host wrapper discards LAPACKE's
status. IPPL does not patch upstream or suppress compiler diagnostics. This test
therefore validates portable map construction and an explicit host eigenanalysis
boundary, not a GPU eigensolver or the experimental wrapper.

```sh
cmake --build build_openmp --target KokkosKernelsLinearMap
OMP_NUM_THREADS=2 ctest --test-dir build_openmp -R '^KokkosKernelsLinearMap$' --output-on-failure
```

Reference: [Kokkos Kernels 5.2.0 eigenanalysis implementation](https://github.com/kokkos/kokkos-kernels/blob/5.2.0/batched/dense/impl/KokkosBatched_Eigendecomposition_Serial_Internal.hpp).

A standalone consumer test checks dependency propagation while linking only
`IPPL::ippl`. Configure it against the IPPL build directory, then repeat with
`IPPL_DIR=<install-prefix>/lib/cmake/ippl` after installation:

```sh
cmake -S cmake/tests/KokkosKernelsConsumer -B build/kernels-consumer -DIPPL_DIR="$PWD/build_openmp"
cmake --build build/kernels-consumer
OMP_NUM_THREADS=2 build/kernels-consumer/consumer
```

Use the same compiler/toolchain as the IPPL build. The CSCS dashboard script
forwards the host-provider, fallback, compiler and dependency-path options above.
Site images can supply LAPACKE or host C/Fortran compilers for the fallback.
12 changes: 12 additions & 0 deletions cmake/Dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,18 @@ else()
# git tag, please use one of these:\n" "${KOKKOS_GIT_TAGS}") endif()
endif()

# ------------------------------------------------------------------------------
# ~~~
# Kokkos Kernels
# ------------------------------------------------------------------------------
set(IPPL_KOKKOS_PACKAGE_HINT "${Kokkos_DIR}")
if(NOT Kokkos_FOUND)
set(IPPL_KOKKOS_PACKAGE_HINT "${kokkos_BINARY_DIR}")
endif()
if(IPPL_ENABLE_KOKKOS_KERNELS)
include(KokkosKernelsDependency)
endif()

# ------------------------------------------------------------------------------
# ~~~
# Heffte (only if FFT enabled)
Expand Down
72 changes: 72 additions & 0 deletions cmake/FetchHostLapack.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Bootstrap the host library at configure time so the normal link/runtime probes
# still validate a real library on the first configure. Subsequent builds reuse it.
function(ippl_fetch_host_lapack)
if(CMAKE_CROSSCOMPILING AND NOT IPPL_LAPACKE_TOOLCHAIN_FILE)
message(FATAL_ERROR "LAPACKE fallback in a cross build needs IPPL_LAPACKE_TOOLCHAIN_FILE for the target CPU, or an installed LAPACKE provider.")
endif()
set(IPPL_LAPACKE_BUILD_JOBS 4 CACHE STRING "Parallel jobs for reference LAPACK bootstrap")
set(IPPL_LAPACKE_TOOLCHAIN_FILE "" CACHE FILEPATH "Optional host LAPACK C/Fortran toolchain")
FetchContent_Declare(ippl_reference_lapack
URL https://codeload.github.com/Reference-LAPACK/lapack/tar.gz/refs/tags/v3.12.1
URL_HASH SHA256=2ca6407a001a474d4d4d35f3a61550156050c48016d949f0da0529c0aa052422
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
SOURCE_SUBDIR ippl-bootstrap-only)
FetchContent_MakeAvailable(ippl_reference_lapack)
set(_build "${FETCHCONTENT_BASE_DIR}/ippl-host-lapack-${IPPL_LAPACK_INTEGER_BYTES}-build")
set(_prefix "${FETCHCONTENT_BASE_DIR}/ippl-host-lapack-${IPPL_LAPACK_INTEGER_BYTES}-install")
set(_options)
# Let the host project discover C independently (or use CC/the toolchain).
# IPPL may enable C only later through a dependency, so forwarding its C
# compiler would change the bootstrap compiler on the second configure.
foreach(_variable CMAKE_Fortran_COMPILER CMAKE_OSX_ARCHITECTURES CMAKE_OSX_SYSROOT CMAKE_OSX_DEPLOYMENT_TARGET)
if(DEFINED ${_variable} AND NOT "${${_variable}}" STREQUAL "")
if(_variable MATCHES "_COMPILER$")
list(APPEND _options "-D${_variable}:FILEPATH=${${_variable}}")
else()
list(APPEND _options "-D${_variable}:STRING=${${_variable}}")
endif()
endif()
endforeach()
if(IPPL_LAPACKE_TOOLCHAIN_FILE)
list(APPEND _options "-DCMAKE_TOOLCHAIN_FILE=${IPPL_LAPACKE_TOOLCHAIN_FILE}")
endif()
message(STATUS "Host LAPACKE not found: building reference LAPACK 3.12.1 (C/Fortran); logs in ${_build}")
file(MAKE_DIRECTORY "${_build}")
execute_process(COMMAND "${CMAKE_COMMAND}"
-S "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/lapack-bootstrap" -B "${_build}"
"-DIPPL_REFERENCE_LAPACK_SOURCE_DIR=${ippl_reference_lapack_SOURCE_DIR}"
"-DIPPL_LAPACK_INTEGER_BYTES=${IPPL_LAPACK_INTEGER_BYTES}"
"-DCMAKE_INSTALL_PREFIX=${_prefix}" -DCMAKE_BUILD_TYPE=Release ${_options}
RESULT_VARIABLE _result OUTPUT_FILE "${_build}/configure.log" ERROR_FILE "${_build}/configure.log")
if(NOT _result EQUAL 0)
message(FATAL_ERROR "Host LAPACKE bootstrap configure failed. A host C and Fortran compiler (e.g. gfortran) is required. See ${_build}/configure.log")
endif()
execute_process(COMMAND "${CMAKE_COMMAND}" --build "${_build}" --config Release
--parallel "${IPPL_LAPACKE_BUILD_JOBS}"
RESULT_VARIABLE _result OUTPUT_FILE "${_build}/build.log" ERROR_FILE "${_build}/build.log")
if(NOT _result EQUAL 0)
message(FATAL_ERROR "Host LAPACKE bootstrap build failed; see ${_build}/build.log")
endif()
execute_process(COMMAND "${CMAKE_COMMAND}" --install "${_build}" --config Release
RESULT_VARIABLE _result OUTPUT_FILE "${_build}/install.log" ERROR_FILE "${_build}/install.log")
if(NOT _result EQUAL 0)
message(FATAL_ERROR "Host LAPACKE bootstrap install failed; see ${_build}/install.log")
endif()
# Use this exact bootstrap, including after a change of integer ABI.
set(IPPLHostLapack_DIR "${_prefix}/lib/cmake/IPPLHostLapack")
find_package(IPPLHostLapack CONFIG REQUIRED NO_DEFAULT_PATH PATHS "${IPPLHostLapack_DIR}")
# Imported targets created inside a function retain their directory visibility.
# Bundle only the private archives, public headers and our relocatable package;
# upstream pkg-config files contain the bootstrap prefix and are not exported.
install(DIRECTORY "${_prefix}/include/ippl-lapack" DESTINATION include)
install(DIRECTORY "${_prefix}/lib/ippl-lapack/" DESTINATION lib/ippl-lapack
FILES_MATCHING PATTERN "*.a" PATTERN "*.lib"
PATTERN "cmake" EXCLUDE PATTERN "pkgconfig" EXCLUDE)
install(FILES "${_prefix}/lib/cmake/IPPLHostLapack/IPPLHostLapackConfig.cmake"
DESTINATION lib/cmake/IPPLHostLapack)
install(FILES "${_prefix}/share/ippl/LAPACK-LICENSE" DESTINATION share/ippl)
set(LAPACKE_INCLUDE_DIRS "${_prefix}/include/ippl-lapack" PARENT_SCOPE)
set(LAPACKE_LIBRARIES IPPLHostLapack::lapacke PARENT_SCOPE)
set(IPPL_HOST_LAPACK_PREFIX "${_prefix}" PARENT_SCOPE)
set(IPPL_HOST_LAPACK_FETCHED ON PARENT_SCOPE)
endfunction()
43 changes: 43 additions & 0 deletions cmake/FindTPLLAPACKE.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# IPPL has already resolved the complete host link line. Preserve absolute paths
# and static transitive dependencies; upstream 5.2's finder treats them as names.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(TPLLAPACKE REQUIRED_VARS LAPACKE_INCLUDE_DIRS LAPACKE_LIBRARIES)
set(_lapackeResolved)
foreach(_library IN LISTS LAPACKE_LIBRARIES)
if(TARGET "${_library}")
list(APPEND _lapackeResolved "${_library}")
elseif(_library MATCHES "^-")
# CMake LAPACK providers may return linker items such as -lm or -pthread.
# Preserve them verbatim instead of treating them as find_library names.
list(APPEND _lapackeResolved "${_library}")
elseif(IS_ABSOLUTE "${_library}")
if(NOT EXISTS "${_library}")
message(FATAL_ERROR "LAPACKE dependency does not exist: ${_library}")
endif()
list(APPEND _lapackeResolved "${_library}")
else()
unset(_lapackeLibrary CACHE)
find_library(_lapackeLibrary NAMES ${_library} HINTS ${LAPACKE_LIBRARY_DIRS} REQUIRED)
list(APPEND _lapackeResolved "${_lapackeLibrary}")
endif()
endforeach()
set(_lapackeIncludes "${LAPACKE_INCLUDE_DIRS}")
if(IPPL_HOST_LAPACK_FETCHED)
# The imported host target carries relocatable include directories itself.
set(_lapackeIncludes)
endif()
kokkoskernels_create_imported_tpl(LAPACKE INTERFACE
LINK_LIBRARIES "${_lapackeResolved}")
if(_lapackeIncludes)
# Environment views may also contain an incompatible desul installation.
# Keep their broad include directory behind Kokkos's bundled TPL headers.
target_include_directories(LAPACKE SYSTEM INTERFACE ${_lapackeIncludes})
endif()

if(IPPL_HOST_LAPACK_FETCHED)
# Also make the Kernels package usable directly, including in a fresh IPPL
# build that finds this Kernels installation instead of fetching its sources.
kokkoskernels_append_config_line("include(CMakeFindDependencyMacro)")
kokkoskernels_append_config_line(
"find_dependency(IPPLHostLapack CONFIG HINTS \"\\\${PACKAGE_PREFIX_DIR}\" \"${IPPL_HOST_LAPACK_PREFIX}\")")
endif()
Loading
Loading