Skip to content
Draft
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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# CMake
/build/
CMakeUserPresets.json
/CMakeCache.txt
/CMakeFiles/

*.bck
*.o
*.mod
Expand Down
167 changes: 167 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
cmake_minimum_required(VERSION 3.20)

# The version header embeds the compile flags, so languages must be enabled
# before we can generate it. Fortran is the primary language; C and C++ are
# needed for tools/*.c, the r-tree, the sparse-solver shims and Catalyst.
project(JOREK
LANGUAGES Fortran C CXX
DESCRIPTION "Non-linear extended MHD code for toroidal X-point geometries")

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR
"In-source builds are not supported. Configure into a separate directory, "
"e.g. cmake --preset pitagora-intel")
endif()

set(CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

include(JorekOptions) # cache options, replaces Makefile.inc switches
include(JorekModelConfig) # derive -D flags from the model settings files
include(JorekCompilerFlags) # per-compiler flag sets, replaces defaults.mk
include(JorekDependencies) # MPI, HDF5, FFTW, BLAS/LAPACK, sparse solvers
include(JorekVersion) # git-derived version.h
include(JorekSources) # source discovery, program/library split

# --- Usage requirements shared by every JOREK target ------------------------
add_library(jorek_common INTERFACE)
target_include_directories(jorek_common INTERFACE
"${CMAKE_BINARY_DIR}/generated" # version.h
"${JOREK_GENERATED_INCLUDE_DIR}" # rhs/amat/aux_automatic.h
"${CMAKE_CURRENT_SOURCE_DIR}/tools" # r3_info.h
"${CMAKE_CURRENT_SOURCE_DIR}/models"
${JOREK_INCLUDE_DIRS})
target_compile_definitions(jorek_common INTERFACE ${JOREK_DEFINES})
target_link_libraries(jorek_common INTERFACE ${JOREK_LIBRARIES})

# --- The code generator (semianalytical models only) ------------------------
#
# Built before, and independently of, the core library -- see JorekSources for
# why it cannot simply link against it. Its objects are compiled a second time
# into jorek_core; that is a dozen files, and it keeps the graph acyclic.
if(JOREK_SEMIANALYTICAL)
add_library(jorek_codegen STATIC ${JOREK_CODEGEN_SOURCES})
add_dependencies(jorek_codegen jorek_version_header)
target_link_libraries(jorek_codegen PRIVATE jorek_common)
# Its own module directory: these sources are also compiled into jorek_core,
# and the two must not fight over the same .mod files.
set_target_properties(jorek_codegen PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules_codegen")

# algexpr2fort evaluates the model's symbolic equations and writes the
# RHS/AMAT/AUX Fortran that mod_elt_matrix{,_fft}.f90 #include. It hard-codes
# its output path as "models/model<NNN>/<name>.h" relative to the working
# directory, so run it from the build tree to keep the source tree clean.
add_executable(algexpr2fort "${CMAKE_CURRENT_SOURCE_DIR}/models/algexpr2fort.f90")
target_link_libraries(algexpr2fort PRIVATE jorek_codegen jorek_common)
set_target_properties(algexpr2fort PROPERTIES
Fortran_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/modules_codegen"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
LINKER_LANGUAGE Fortran)

set(JOREK_GENERATED_HEADERS
"${JOREK_GENERATED_INCLUDE_DIR}/rhs_automatic.h"
"${JOREK_GENERATED_INCLUDE_DIR}/amat_automatic.h"
"${JOREK_GENERATED_INCLUDE_DIR}/aux_automatic.h")

add_custom_command(
OUTPUT ${JOREK_GENERATED_HEADERS}
COMMAND "$<TARGET_FILE:algexpr2fort>"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/generated"
DEPENDS algexpr2fort
COMMENT "Generating element-matrix code for ${JOREK_MODEL}"
VERBATIM)
add_custom_target(jorek_generated_code DEPENDS ${JOREK_GENERATED_HEADERS})
endif()

# --- The core library -------------------------------------------------------
#
# The Make build discovered each executable's objects by scanning for `call`
# statements and linking whatever file was named after the callee. Here every
# non-program source instead goes into one static archive, and the linker
# extracts what each executable actually references. Keeping it a single archive
# matters: JOREK is full of bare external subroutines, so any split into two
# libraries would leave them referencing each other across the link line.
add_library(jorek_core STATIC ${JOREK_LIB_SOURCES})
add_dependencies(jorek_core jorek_version_header)
target_link_libraries(jorek_core PUBLIC jorek_common)
target_include_directories(jorek_core PUBLIC "${CMAKE_Fortran_MODULE_DIRECTORY}")

if(JOREK_SEMIANALYTICAL)
add_dependencies(jorek_core jorek_generated_code)
endif()

# --- Executables ------------------------------------------------------------
#
# Only the main solver is built by default, mirroring `make`. Every other
# program is a named target; `make most` builds the regression-tested subset.
foreach(_prog_src IN LISTS JOREK_PROGRAM_SOURCES)
get_filename_component(_prog "${_prog_src}" NAME_WE)

if(_prog STREQUAL "jorek2_main")
add_executable(jorek2_main "${_prog_src}")
set_target_properties(jorek2_main PROPERTIES
OUTPUT_NAME "jorek_model${JOREK_MODEL_NUMBER}")
else()
add_executable(${_prog} EXCLUDE_FROM_ALL "${_prog_src}")
endif()

target_link_libraries(${_prog} PRIVATE jorek_core)
set_target_properties(${_prog} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
# The core library mixes Fortran, C and C++ objects, and CMake would
# otherwise pick the C++ driver to link -- which does not supply the
# Fortran runtime's main(). Every JOREK program is a Fortran program.
LINKER_LANGUAGE Fortran)
endforeach()

if(TARGET eqdsk2jorek AND JOREK_DIERCKX_LIBRARIES)
target_link_libraries(eqdsk2jorek PRIVATE ${JOREK_DIERCKX_LIBRARIES})
endif()

# The set of diagnostics that must keep compiling for regression testing to
# pass. Kept in sync with the `most:` target of the legacy Makefile.
set(JOREK_MOST_TARGETS
jorek2_connection2
jorek2_connection_stan
jorek2_connection_flux_aligned
jorek2_diagno
jorek2_diagno_spi
jorek2_fieldlines_vtk
jorek2_four
CARIDDI_wall_curr
jorek2_poincare
jorek2_powers
jorek2_target2vtk
jorek2vtk_3d
jorek2vtk
jorek2vtk_GaussVortTerms
test_gvec2jorek_import
jorek_to_helena
new_diag_demo
jorek2_postproc
rst_bin2hdf5
rst_hdf52bin
jorek2_main)
if(JOREK_USE_IMAS)
list(APPEND JOREK_MOST_TARGETS jorek2_IDS)
endif()

set(_most_existing "")
foreach(_t IN LISTS JOREK_MOST_TARGETS)
if(TARGET ${_t})
list(APPEND _most_existing ${_t})
else()
message(WARNING "'most' target references unknown program '${_t}'")
endif()
endforeach()
add_custom_target(most DEPENDS ${_most_existing})

include(JorekSummary)
174 changes: 174 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "base",
"hidden": true,
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"JOREK_MODEL": "model600"
}
},
{
"name": "pitagora-intel",
"inherits": "base",
"displayName": "Pitagora CPU - Intel oneAPI + MKL + STRUMPACK",
"description": "Requires: module load intel-oneapi-mpi intel-oneapi-compilers intel-oneapi-mkl/2024.0.0--intel-oneapi-mpi--2021.12.1 hdf5/1.14.3--intel-oneapi-mpi--2021.12.1--oneapi--2024.1.0 cmake",
"cacheVariables": {
"CMAKE_Fortran_COMPILER": "mpiifx",
"CMAKE_C_COMPILER": "mpiicx",
"CMAKE_CXX_COMPILER": "mpiicpx",
"CMAKE_Fortran_FLAGS": "-mcmodel=medium -march=skylake-avx512 -axCORE-AVX512",
"CMAKE_C_FLAGS": "-mcmodel=medium -march=skylake-avx512 -axCORE-AVX512",
"CMAKE_CXX_FLAGS": "-mcmodel=medium -march=skylake-avx512 -axCORE-AVX512",
"JOREK_USE_MKL": "ON",
"JOREK_USE_STRUMPACK": "ON",
"JOREK_USE_MUMPS": "OFF",
"JOREK_USE_PASTIX": "OFF",
"JOREK_USE_HDF5": "ON",
"JOREK_USE_FFTW": "ON",
"JOREK_USE_BLOCK": "ON",
"JOREK_LIB_DIR": "/pitagora_work/FUPA1_MHD/JOREK_LIBRARIES/libraries_recompile_amd",
"STRUMPACK_ROOT": "/pitagora_work/FUPA1_MHD/JOREK_LIBRARIES/libraries_recompile_amd/STRUMPACK/install",
"METIS_ROOT": "/pitagora_work/FUPA1_MHD/JOREK_LIBRARIES/libraries_recompile_amd/METIS/install",
"PARMETIS_ROOT": "/pitagora_work/FUPA1_MHD/JOREK_LIBRARIES/libraries_recompile_amd/ParMETIS/install",
"GKLIB_ROOT": "/pitagora_work/FUPA1_MHD/JOREK_LIBRARIES/libraries_recompile_amd/GKlib/install"
}
},
{
"name": "pitagora-intel-debug",
"inherits": "pitagora-intel",
"displayName": "Pitagora CPU - Intel oneAPI, debug build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "viper-intel",
"inherits": "base",
"displayName": "Viper CPU - Intel oneAPI + MKL + STRUMPACK (AMD Genoa/Zen4)",
"description": "Requires: module purge && module load intel/2025.3 impi/2021.17 mkl/2025.3 hdf5-mpi/2.0.0 fftw-mpi/3.3.10 cmake",
"cacheVariables": {
"CMAKE_Fortran_COMPILER": "mpiifx",
"CMAKE_C_COMPILER": "mpiicx",
"CMAKE_CXX_COMPILER": "mpiicpx",
"CMAKE_Fortran_FLAGS": "-mcmodel=medium -march=znver4",
"CMAKE_C_FLAGS": "-mcmodel=medium -march=znver4",
"CMAKE_CXX_FLAGS": "-mcmodel=medium -march=znver4",
"JOREK_USE_MKL": "ON",
"JOREK_USE_STRUMPACK": "ON",
"JOREK_USE_MUMPS": "OFF",
"JOREK_USE_PASTIX": "OFF",
"JOREK_USE_HDF5": "ON",
"JOREK_USE_FFTW": "ON",
"JOREK_USE_BLOCK": "ON",
"JOREK_LIB_DIR": "/u/edocarr/libs/intel_25_03/",
"STRUMPACK_ROOT": "/u/edocarr/libs/intel_25_03/STRUMPACK/install",
"METIS_ROOT": "/u/edocarr/libs/intel_25_03/METIS/install",
"PARMETIS_ROOT": "/u/edocarr/libs/intel_25_03/ParMETIS/install",
"GKLIB_ROOT": "/u/edocarr/libs/intel_25_03/GKlib/install"
}
},
{
"name": "viper-intel-debug",
"inherits": "viper-intel",
"displayName": "Viper CPU - Intel oneAPI, debug build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "tok-intel",
"inherits": "base",
"displayName": "TOK CPU - Intel oneAPI + MKL + STRUMPACK (IPP Garching)",
"description": "Requires: module purge && module load intel/2025.1 impi/2021.15 mkl fftw-mpi hdf5-mpi cmake",
"cacheVariables": {
"CMAKE_Fortran_COMPILER": "mpiifx",
"CMAKE_C_COMPILER": "mpiicx",
"CMAKE_CXX_COMPILER": "mpiicpx",
"CMAKE_Fortran_FLAGS": "-mcmodel=medium -march=native",
"CMAKE_C_FLAGS": "-mcmodel=medium -march=native",
"CMAKE_CXX_FLAGS": "-mcmodel=medium -march=native",
"JOREK_USE_MKL": "ON",
"JOREK_USE_STRUMPACK": "ON",
"JOREK_USE_MUMPS": "OFF",
"JOREK_USE_PASTIX": "OFF",
"JOREK_USE_HDF5": "ON",
"JOREK_USE_FFTW": "ON",
"JOREK_USE_BLOCK": "ON",
"JOREK_LIB_DIR": "/tokp/work/mhoelzl/bin-of-ihol/intel",
"STRUMPACK_ROOT": "/tokp/work/mhoelzl/bin-of-ihol/intel/STRUMPACK-7.1.3/install",
"METIS_ROOT": "/tokp/work/mhoelzl/bin-of-ihol/intel/metis_git/install",
"PARMETIS_ROOT": "/tokp/work/mhoelzl/bin-of-ihol/intel/ParMETIS_git/install",
"GKLIB_ROOT": "/tokp/work/mhoelzl/bin-of-ihol/intel/GKlib_git/install"
}
},
{
"name": "tok-intel-debug",
"inherits": "tok-intel",
"displayName": "TOK CPU - Intel oneAPI, debug build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
}
],
"buildPresets": [
{
"name": "pitagora-intel",
"configurePreset": "pitagora-intel",
"jobs": 16
},
{
"name": "pitagora-intel-most",
"configurePreset": "pitagora-intel",
"displayName": "Main solver plus the regression-tested diagnostics",
"targets": ["most"],
"jobs": 16
},
{
"name": "pitagora-intel-debug",
"configurePreset": "pitagora-intel-debug",
"jobs": 16
},
{
"name": "viper-intel",
"configurePreset": "viper-intel",
"jobs": 16
},
{
"name": "viper-intel-most",
"configurePreset": "viper-intel",
"displayName": "Main solver plus the regression-tested diagnostics",
"targets": ["most"],
"jobs": 16
},
{
"name": "viper-intel-debug",
"configurePreset": "viper-intel-debug",
"jobs": 16
},
{
"name": "tok-intel",
"configurePreset": "tok-intel",
"jobs": 16
},
{
"name": "tok-intel-most",
"configurePreset": "tok-intel",
"displayName": "Main solver plus the regression-tested diagnostics",
"targets": ["most"],
"jobs": 16
},
{
"name": "tok-intel-debug",
"configurePreset": "tok-intel-debug",
"jobs": 16
}
]
}
34 changes: 34 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,40 @@

For a documentation about the code, see jorek.eu/wiki


=======================================================
Building with CMake (recommended)
=======================================================

Each supported machine is a CMake preset in CMakePresets.json. To list them:

cmake --list-presets

Pick the preset for your machine (e.g. viper-intel, pitagora-intel; add
-debug for a debug build). Each preset's "description" field states the exact
`module load` line to run first.

# 1. load the modules listed in the preset's description
# 2. configure once
cmake --preset <preset>

# 3. build (build tree is build/<preset>/)
cmake --build build/<preset> -j 16 # default: main solver
cmake --build build/<preset> --target jorek2_diagno -j 16 # a specific program
cmake --build build/<preset> --target help # list all targets

Every .f90 file with a `program` statement becomes a target named after the
file; the built executables land in build/<preset>/. Set the model and options
per preset in CMakePresets.json (JOREK_MODEL, JOREK_USE_*), not in Makefile.inc.


=======================================================
Building with Makefile.inc (DEPRECATED)
=======================================================

NOTE: the Makefile.inc / `make` build below is deprecated. Prefer the CMake
build above. The instructions are kept for reference only.

to build jorek2:

- edit the Makefile.inc file to match your environment
Expand Down
Loading
Loading