From d6fff3cdbe6cb428630d59a6cda9d9030b680e40 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Wed, 10 Jun 2026 14:28:55 -0400 Subject: [PATCH] build(meson): much more robust build system --- benchmarks/Memory/main.cpp | 2 +- .../SingleZoneSolver/gf_wall_vs_temp.cpp | 2 +- benchmarks/SingleZoneSolver/main.cpp | 2 +- benchmarks/Timing/main.cpp | 2 +- build-config/cppad/meson.build | 47 +++-- build-config/eigen/meson.build | 18 +- build-config/fourdst/meson.build | 72 +++++-- build-config/json/meson.build | 6 + build-config/meson.build | 36 +++- build-config/python/meson.build | 3 +- build-config/sundials/cvode/meson.build | 90 +++++---- build-config/sundials/kinsol/meson.build | 49 +++-- build-config/sundials/meson.build | 8 + build-config/sundials/vendor/meson.build | 46 +++++ build-config/xxHash/meson.build | 7 +- build-extra/pkg-config/gridfire-wheel.pc.in | 9 + build-extra/pkg-config/meson.build | 35 ++-- build-python/meson.build | 179 +++++++++--------- meson_options.txt | 4 +- pip_install_mac_patch.sh | 123 +++++------- pyproject.toml | 30 ++- src/include/gridfire/engine/engine_graph.h | 2 - .../gridfire/solver/strategies/PointSolver.h | 20 ++ src/include/gridfire/utils/meson.build | 12 +- src/lib/engine/procedures/priming.cpp | 2 +- src/lib/policy/stellar_policy.cpp | 2 +- src/lib/solver/strategies/PointSolver.cpp | 22 +++ src/meson.build | 76 +++++--- subprojects/fourdst.wrap | 2 +- tests/graphnet_sandbox/main.cpp | 2 +- tools/gf_bbn/main.cpp | 6 +- tools/gf_multi/main.cpp | 8 +- tools/gf_quick/main.cpp | 7 +- 33 files changed, 571 insertions(+), 360 deletions(-) create mode 100644 build-config/sundials/vendor/meson.build create mode 100644 build-extra/pkg-config/gridfire-wheel.pc.in diff --git a/benchmarks/Memory/main.cpp b/benchmarks/Memory/main.cpp index 4f468acd..337d71e3 100644 --- a/benchmarks/Memory/main.cpp +++ b/benchmarks/Memory/main.cpp @@ -9,7 +9,7 @@ #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" diff --git a/benchmarks/SingleZoneSolver/gf_wall_vs_temp.cpp b/benchmarks/SingleZoneSolver/gf_wall_vs_temp.cpp index d014687e..6584ff1a 100644 --- a/benchmarks/SingleZoneSolver/gf_wall_vs_temp.cpp +++ b/benchmarks/SingleZoneSolver/gf_wall_vs_temp.cpp @@ -11,7 +11,7 @@ #include "fourdst/composition/composition.h" #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" diff --git a/benchmarks/SingleZoneSolver/main.cpp b/benchmarks/SingleZoneSolver/main.cpp index 5d10f6df..a27cdffc 100644 --- a/benchmarks/SingleZoneSolver/main.cpp +++ b/benchmarks/SingleZoneSolver/main.cpp @@ -11,7 +11,7 @@ #include "fourdst/composition/composition.h" #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" diff --git a/benchmarks/Timing/main.cpp b/benchmarks/Timing/main.cpp index 4584d7ad..73da904f 100644 --- a/benchmarks/Timing/main.cpp +++ b/benchmarks/Timing/main.cpp @@ -7,7 +7,7 @@ #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" diff --git a/build-config/cppad/meson.build b/build-config/cppad/meson.build index f2ea47d8..1d291b4e 100644 --- a/build-config/cppad/meson.build +++ b/build-config/cppad/meson.build @@ -1,13 +1,12 @@ cppad_cmake_options = cmake.subproject_options() cppad_cmake_options.add_cmake_defines({ - 'cppad_static_lib': 'true', - 'cpp_mas_num_threads': '10', - 'cppad_debug_and_release': 'false', - 'include_doc': 'false', - 'CMAKE_POSITION_INDEPENDENT_CODE': true -}) - + 'cppad_static_lib': 'true', + 'cpp_mas_num_threads': '10', + 'cppad_debug_and_release': 'false', + 'include_doc': 'false', + 'CMAKE_POSITION_INDEPENDENT_CODE': true + }) cppad_cmake_options.set_install(false) cppad_sp = cmake.subproject( @@ -22,22 +21,28 @@ cppad_incs = cppad_sp.include_directories('cppad_lib') empty_cppad_file = configure_file(output: 'cppad_dummy_ar.cpp', command: ['echo'], capture: true) libcppad_static = static_library( - 'cppad-static', - empty_cppad_file, - objects: cppad_objs, - include_directories: cppad_incs, - pic: true, - install: false + 'cppad-static', + empty_cppad_file, + objects: cppad_objs, + include_directories: cppad_incs, + pic: true, + install: false ) cppad_dep = declare_dependency( - link_with: libcppad_static, - include_directories: cppad_incs + include_directories: cppad_incs ) -message('Installing CppAD headers to ' + get_option('includedir')) -install_subdir( - 'subprojects/CppAD-20250000.2/include', - install_dir: get_option('includedir'), - strip_directory: true -) +message('Staging vendored CppAD headers for ' + gridfire_vendor_includedir) + +custom_target( + 'vendor_cppad_headers', + command: copytree_cmd + [ + meson.project_source_root() / 'subprojects' / 'CppAD-20250000.2' / 'include' / 'cppad', + '@OUTPUT@', + ], + output: 'cppad', + depends: libcppad_static, + install: true, + install_dir: gridfire_vendor_includedir, +) \ No newline at end of file diff --git a/build-config/eigen/meson.build b/build-config/eigen/meson.build index 5c5a0a1c..be3c9e5f 100644 --- a/build-config/eigen/meson.build +++ b/build-config/eigen/meson.build @@ -1,5 +1,13 @@ -eigen_dep = dependency( - 'eigen3', - version : '>=3.3', - fallback : ['eigen', 'eigen_dep'] -).as_system() \ No newline at end of file +eigen_sp = subproject('eigen') +eigen_dep = eigen_sp.get_variable('eigen_dep').as_system() + +custom_target( + 'vendor_eigen_headers', + command: copytree_cmd + [ + meson.project_source_root() / 'subprojects' / 'eigen-3.4.0' / 'Eigen', + '@OUTPUT@', + ], + output: 'Eigen', + install: true, + install_dir: gridfire_vendor_includedir, +) diff --git a/build-config/fourdst/meson.build b/build-config/fourdst/meson.build index d2b092a0..093aa317 100644 --- a/build-config/fourdst/meson.build +++ b/build-config/fourdst/meson.build @@ -1,23 +1,25 @@ -# bring in all of the fourdst utility repositories - fourdst_build_lib_all = true if not get_option('plugin_support') fourdst_build_lib_all=false message('Disabling fourdst plugin support as per user request.') endif -fourdst_sp = subproject('fourdst', - default_options: - ['build_tests=' + get_option('build_tests').to_string(), - 'build_python=' + get_option('build_python').to_string(), - 'build_lib_all=' + fourdst_build_lib_all.to_string(), - 'build_lib_comp=true', - 'build_lib_config=true', - 'build_lib_log=true', - 'build_lib_const=true', - 'pkg_config=' + get_option('pkg_config').to_string(), - ] -) +fourdst_default_options = [ + 'build_tests=' + get_option('build_tests').to_string(), + 'build_python=' + get_option('build_python').to_string(), + 'build_lib_all=' + fourdst_build_lib_all.to_string(), + 'build_lib_comp=true', + 'build_lib_config=true', + 'build_lib_log=true', + 'build_lib_const=true', + 'pkg_config=' + get_option('pkg_config').to_string(), +] + +if get_option('build_python') + fourdst_default_options += ['default_library=static'] +endif + +fourdst_sp = subproject('fourdst', default_options: fourdst_default_options) composition_dep = fourdst_sp.get_variable('composition_dep') log_dep = fourdst_sp.get_variable('log_dep') @@ -36,3 +38,45 @@ if get_option('plugin_support') warning('Including plugin library from fourdst. Note this will bring in minizip-ng and openssl, which can cause build issues with cross compilation due to their complexity.') libplugin = fourdst_sp.get_variable('libplugin') endif + +if get_option('build_python') + sp_root = meson.project_source_root() / 'subprojects' + + fourdst_header_trees = [ + + ['config', + sp_root / 'libconfig' / 'src' / 'config' / 'include' / 'fourdst' / 'config', + gridfire_includedir / 'fourdst'], + ['composition', + sp_root / 'libcomposition' / 'src' / 'composition' / 'include' / 'fourdst' / 'composition', + gridfire_includedir / 'fourdst'], + ['atomic', + sp_root / 'libcomposition' / 'src' / 'composition' / 'include' / 'fourdst' / 'atomic', + gridfire_includedir / 'fourdst'], + ['constants', + sp_root / 'libconstants' / 'src' / 'constants' / 'include' / 'fourdst' / 'constants', + gridfire_includedir / 'fourdst'], + ['logging', + sp_root / 'liblogging' / 'src' / 'logging' / 'include' / 'fourdst' / 'logging', + gridfire_includedir / 'fourdst'], + ['toml++', + sp_root / 'libconfig' / 'build-config' / 'tomlpp' / 'vendor' / 'include' / 'toml++', + gridfire_fourdst_vendor_includedir], + ['quill', + sp_root / 'quill' / 'include' / 'quill', + gridfire_fourdst_vendor_includedir], + ['CLI', + sp_root / 'CLI11-2.6.1' / 'include' / 'CLI', + gridfire_fourdst_vendor_includedir], + ] + + foreach t : fourdst_header_trees + custom_target( + 'wheel_headers_' + t[0].underscorify(), + command: copytree_cmd + [t[1], '@OUTPUT@'], + output: t[0], + install: true, + install_dir: t[2], + ) + endforeach +endif diff --git a/build-config/json/meson.build b/build-config/json/meson.build index f443bb58..8b83c22a 100644 --- a/build-config/json/meson.build +++ b/build-config/json/meson.build @@ -1,3 +1,9 @@ json_dep = declare_dependency( include_directories: include_directories('include') ) + +install_subdir( + 'include', + install_dir: gridfire_vendor_includedir, + strip_directory: true, +) diff --git a/build-config/meson.build b/build-config/meson.build index 18e455bf..b450c96b 100644 --- a/build-config/meson.build +++ b/build-config/meson.build @@ -4,6 +4,41 @@ if get_option('build_python') subdir('python') subdir('pybind') endif + +if get_option('build_python') + gridfire_pkg_dir = py_installation.get_install_dir() / 'gridfire' + gridfire_includedir = gridfire_pkg_dir / 'include' + gridfire_libdir = gridfire_pkg_dir / 'lib' + gridfire_pcdir = gridfire_libdir / 'pkgconfig' +else + gridfire_includedir = get_option('includedir') + gridfire_libdir = get_option('libdir') + gridfire_pcdir = get_option('libdir') / 'pkgconfig' +endif + +gridfire_vendor_includedir = gridfire_includedir / 'gridfire' / 'vendor' + +gridfire_fourdst_vendor_includedir = gridfire_includedir / 'fourdst' / 'vendor' + +vendor_py = import('python').find_installation('python3') +copytree_cmd = [ + vendor_py, '-c', + '''import sys, os, stat, shutil +src, dst = sys.argv[1], sys.argv[2] +shutil.rmtree(dst, ignore_errors=True) +shutil.copytree(src, dst) +for root, dirs, files in os.walk(dst): + os.chmod(root, 0o755) + for f in files: + p = os.path.join(root, f) + os.chmod(p, os.stat(p).st_mode | 0o644) +''', +] +copyfiles_cmd = [ + vendor_py, '-c', + 'import sys, shutil; [shutil.copy2(p, sys.argv[-1]) for p in sys.argv[1:-1]]', +] + subdir('fourdst') subdir('sundials') @@ -14,7 +49,6 @@ subdir('eigen') subdir('json') subdir('CLI11') -subdir('unordered_dense') if get_option('use_mimalloc') subdir('mimalloc') diff --git a/build-config/python/meson.build b/build-config/python/meson.build index 222c14ec..d264b9ff 100644 --- a/build-config/python/meson.build +++ b/build-config/python/meson.build @@ -1,8 +1,7 @@ py_installation = import('python').find_installation('python3', pure: false) - if meson.is_cross_build() and host_machine.system() == 'darwin' - py_ver = get_option('python-target-version') + py_ver = get_option('python_target_version') message('Cross build on Darwin, using python version ' + py_ver) py_inc_dir = include_directories('../../cross/python_includes/python-' + py_ver + '/include/python' + py_ver) py_dep = declare_dependency(include_directories: py_inc_dir) diff --git a/build-config/sundials/cvode/meson.build b/build-config/sundials/cvode/meson.build index 6ffb7ad3..970bff44 100644 --- a/build-config/sundials/cvode/meson.build +++ b/build-config/sundials/cvode/meson.build @@ -1,32 +1,34 @@ cmake = import('cmake') cvode_cmake_options = cmake.subproject_options() -cvode_cmake_options.add_cmake_defines({ - 'CMAKE_CXX_FLAGS' : '-Wno-deprecated-declarations', - 'CMAKE_C_FLAGS' : '-Wno-deprecated-declarations', - 'BUILD_SHARED_LIBS' : 'OFF', - 'BUILD_STATIC_LIBS' : 'ON', - 'EXAMPLES_ENABLE_C' : 'OFF', - 'CMAKE_POSITION_INDEPENDENT_CODE': true, - 'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON', - 'SUNDIALS_LOGGING_LEVEL': 1 - -}) +sundials_hidden_flags = '-Wno-deprecated-declarations -fvisibility=hidden -fvisibility-inlines-hidden' cvode_cmake_options.add_cmake_defines({ - 'CMAKE_INSTALL_LIBDIR': get_option('libdir'), - 'CMAKE_INSTALL_INCLUDEDIR': get_option('includedir') -}) + 'CMAKE_CXX_FLAGS' : sundials_hidden_flags, + 'CMAKE_C_FLAGS' : sundials_hidden_flags, + 'BUILD_SHARED_LIBS' : 'OFF', + 'BUILD_STATIC_LIBS' : 'ON', + 'EXAMPLES_ENABLE_C' : 'OFF', + 'CMAKE_POSITION_INDEPENDENT_CODE': true, + 'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON', + 'SUNDIALS_LOGGING_LEVEL': 1 + + }) + +cvode_cmake_options.add_cmake_defines({ + 'CMAKE_INSTALL_LIBDIR': get_option('libdir'), + 'CMAKE_INSTALL_INCLUDEDIR': get_option('includedir') + }) cvode_cmake_options.set_install(false) if meson.is_cross_build() and host_machine.system() == 'emscripten' - cvode_cmake_options.add_cmake_defines({ - 'CMAKE_C_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1', - 'CMAKE_CXX_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1', - 'CMAKE_SHARED_LINKER_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1', - 'CMAKE_EXE_LINKER_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1' - }) + cvode_cmake_options.add_cmake_defines({ + 'CMAKE_C_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1', + 'CMAKE_CXX_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1', + 'CMAKE_SHARED_LINKER_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1', + 'CMAKE_EXE_LINKER_FLAGS': '-s MEMORY64=1 -s ALLOW_MEMORY_GROWTH=1' + }) endif cvode_sp = cmake.subproject( @@ -41,11 +43,11 @@ sundials_sunmatrixdense_tgt = cvode_sp.target('sundials_sunmatrixdense_static') sundials_sunlinsoldense_tgt = cvode_sp.target('sundials_sunlinsoldense_static') cvode_objs = [ - sundials_core_tgt.extract_all_objects(recursive: true), - sundials_cvode_tgt.extract_all_objects(recursive: true), - sundials_nvecserial_tgt.extract_all_objects(recursive: true), - sundials_sunmatrixdense_tgt.extract_all_objects(recursive: true), - sundials_sunlinsoldense_tgt.extract_all_objects(recursive: true), + sundials_core_tgt.extract_all_objects(recursive: true), + sundials_cvode_tgt.extract_all_objects(recursive: true), + sundials_nvecserial_tgt.extract_all_objects(recursive: true), + sundials_sunmatrixdense_tgt.extract_all_objects(recursive: true), + sundials_sunlinsoldense_tgt.extract_all_objects(recursive: true), ] sundials_core_includes = cvode_sp.include_directories('sundials_core_static') @@ -55,35 +57,29 @@ sundials_sunmatrixdense_includes = cvode_sp.include_directories('sundials_sunmat sundials_sunlinsoldense_includes = cvode_sp.include_directories('sundials_sunlinsoldense_static') cvode_includes = [ - sundials_core_includes, - sundials_cvode_includes, - sundials_nvecserial_includes, - sundials_sunmatrixdense_includes, - sundials_sunlinsoldense_includes + sundials_core_includes, + sundials_cvode_includes, + sundials_nvecserial_includes, + sundials_sunmatrixdense_includes, + sundials_sunlinsoldense_includes ] - empty_cvode_file = configure_file( - output: 'cvode_dummy_ar.cpp', - command: ['echo'], - capture: true - ) - + output: 'cvode_dummy_ar.cpp', + command: ['echo'], + capture: true +) libcvode_static = static_library( - 'cvode-static', - empty_cvode_file, - objects: cvode_objs, - include_directories: cvode_includes, - pic: true, - install: false + 'cvode-static', + empty_cvode_file, + objects: cvode_objs, + include_directories: cvode_includes, + pic: true, + install: false ) - cvode_dep = declare_dependency( - link_with: libcvode_static, - include_directories: cvode_includes, + include_directories: cvode_includes, ) - - diff --git a/build-config/sundials/kinsol/meson.build b/build-config/sundials/kinsol/meson.build index 0926f1b8..15f48bb8 100644 --- a/build-config/sundials/kinsol/meson.build +++ b/build-config/sundials/kinsol/meson.build @@ -3,20 +3,20 @@ cmake = import('cmake') kinsol_cmake_options = cmake.subproject_options() kinsol_cmake_options.add_cmake_defines({ - 'CMAKE_CXX_FLAGS' : '-Wno-deprecated-declarations', - 'CMAKE_C_FLAGS' : '-Wno-deprecated-declarations', - 'BUILD_SHARED_LIBS' : 'OFF', - 'BUILD_STATIC_LIBS' : 'ON', - 'EXAMPLES_ENABLE_C' : 'OFF', - 'CMAKE_POSITION_INDEPENDENT_CODE': true, - 'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON', - 'SUNDIALS_LOGGING_LEVEL': 1 -}) + 'CMAKE_CXX_FLAGS' : '-Wno-deprecated-declarations -fvisibility=hidden -fvisibility-inlines-hidden', + 'CMAKE_C_FLAGS' : '-Wno-deprecated-declarations -fvisibility=hidden -fvisibility-inlines-hidden', + 'BUILD_SHARED_LIBS' : 'OFF', + 'BUILD_STATIC_LIBS' : 'ON', + 'EXAMPLES_ENABLE_C' : 'OFF', + 'CMAKE_POSITION_INDEPENDENT_CODE': true, + 'CMAKE_PLATFORM_NO_VERSIONED_SONAME': 'ON', + 'SUNDIALS_LOGGING_LEVEL': 1 + }) kinsol_cmake_options.add_cmake_defines({ - 'CMAKE_INSTALL_LIBDIR': get_option('libdir'), - 'CMAKE_INSTALL_INCLUDEDIR': get_option('includedir') -}) + 'CMAKE_INSTALL_LIBDIR': get_option('libdir'), + 'CMAKE_INSTALL_INCLUDEDIR': get_option('includedir') + }) kinsol_cmake_options.set_install(false) @@ -31,25 +31,22 @@ kinsol_includes = kinsol_sp.include_directories('sundials_kinsol_obj_static') kinsol_objs = [sundials_kinsol_static_tgt.extract_all_objects(recursive: false)] empty_kinsol_file = configure_file( - output: 'kinsol_dummy_ar.cpp', - command: ['echo'], - capture: true - ) + output: 'kinsol_dummy_ar.cpp', + command: ['echo'], + capture: true +) libkinsol_static = static_library( - 'kinsol_static', - empty_kinsol_file, - objects: kinsol_objs, - include_directories: kinsol_includes, - pic: true, - install: false + 'kinsol_static', + empty_kinsol_file, + objects: kinsol_objs, + include_directories: kinsol_includes, + pic: true, + install: false ) kinsol_dep = declare_dependency( - link_with: libkinsol_static, - include_directories: kinsol_includes + include_directories: kinsol_includes ) - - diff --git a/build-config/sundials/meson.build b/build-config/sundials/meson.build index bf738c13..d514ee64 100644 --- a/build-config/sundials/meson.build +++ b/build-config/sundials/meson.build @@ -7,3 +7,11 @@ sundials_dep = declare_dependency( kinsol_dep, ], ) + +# Vendor the SUNDIALS public headers (see vendor/meson.build). GridFire's +# installed public headers #include etc., so consumers of +# gridfire.pc must compile against exactly the headers this build used -- +# never whatever SUNDIALS happens to be in /usr/local/include (which may be +# a different version or configuration, e.g. an MPI-enabled build whose +# sundials_config.h pulls in ). +subdir('vendor') diff --git a/build-config/sundials/vendor/meson.build b/build-config/sundials/vendor/meson.build new file mode 100644 index 00000000..eb55c0fc --- /dev/null +++ b/build-config/sundials/vendor/meson.build @@ -0,0 +1,46 @@ +sundials_src_include = meson.project_source_root() / 'subprojects' / 'cvode-7.5.0' / 'include' +kinsol_src_include = meson.project_source_root() / 'subprojects' / 'kinsol-7.5.0' / 'include' + +sundials_vendor_dirs = [ + 'sundials', # core (includes sundials/priv/) + 'cvode', + 'nvector', + 'sunmatrix', + 'sunlinsol', + 'sunnonlinsol', + 'sunmemory', + 'sunadaptcontroller', +] + +foreach d : sundials_vendor_dirs + custom_target( + 'vendor_sundials_' + d, + command: copytree_cmd + [sundials_src_include / d, '@OUTPUT@'], + output: d, + install: true, + install_dir: gridfire_vendor_includedir, + ) +endforeach + +custom_target( + 'vendor_sundials_kinsol', + command: copytree_cmd + [kinsol_src_include / 'kinsol', '@OUTPUT@'], + output: 'kinsol', + install: true, + install_dir: gridfire_vendor_includedir, +) + +sundials_cmake_include = meson.global_build_root() / 'subprojects' / 'cvode-7.5.0' / '__CMake_build' / 'include' / 'sundials' + +custom_target( + 'vendor_sundials_generated', + command: copyfiles_cmd + [ + sundials_cmake_include / 'sundials_config.h', + sundials_cmake_include / 'sundials_export.h', + '@OUTDIR@', + ], + output: ['sundials_config.h', 'sundials_export.h'], + depends: libcvode_static, + install: true, + install_dir: gridfire_vendor_includedir / 'sundials', +) diff --git a/build-config/xxHash/meson.build b/build-config/xxHash/meson.build index 3f98172c..b7d01a88 100644 --- a/build-config/xxHash/meson.build +++ b/build-config/xxHash/meson.build @@ -1,4 +1,9 @@ - xxhash_dep = declare_dependency( include_directories: include_directories('include') ) + +install_subdir( + 'include', + install_dir: gridfire_vendor_includedir, + strip_directory: true, +) diff --git a/build-extra/pkg-config/gridfire-wheel.pc.in b/build-extra/pkg-config/gridfire-wheel.pc.in new file mode 100644 index 00000000..d442684e --- /dev/null +++ b/build-extra/pkg-config/gridfire-wheel.pc.in @@ -0,0 +1,9 @@ +prefix=${pcfiledir}/../.. +includedir=${prefix}/include +libdir=${prefix}/lib + +Name: gridfire +Description: GridFire nuclear reaction network solver (bundled with the gridfire Python wheel) +Version: @VERSION@ +Cflags: -I${includedir} -I${includedir}/gridfire/vendor -I${includedir}/fourdst/vendor +Libs: -L${libdir} -lgridfire -Wl,-rpath,${libdir} diff --git a/build-extra/pkg-config/meson.build b/build-extra/pkg-config/meson.build index c23468f3..3712066a 100644 --- a/build-extra/pkg-config/meson.build +++ b/build-extra/pkg-config/meson.build @@ -1,22 +1,29 @@ -if get_option('pkg_config') +if get_option('build_python') + message('Generating wheel-relocatable pkg-config file for GridFire...') + wheel_pc_conf = configuration_data() + wheel_pc_conf.set('VERSION', meson.project_version()) + configure_file( + input: 'gridfire-wheel.pc.in', + output: 'gridfire.pc', + configuration: wheel_pc_conf, + install: true, + install_dir: gridfire_pcdir, + ) +elif get_option('pkg_config') message('Generating pkg-config file for GridFire...') pkg = import('pkgconfig') pkg.generate( + libgridfire, name: 'gridfire', description: 'GridFire nuclear reaction network solver', - version: meson.project_version(), - libraries: [ - libgridfire, - libcomposition, - libconst, - liblogging, - libcppad_static, - libcvode_static, - libkinsol_static - - ], - subdirs: ['gridfire'], filebase: 'gridfire', - install_dir: join_paths(get_option('libdir'), 'pkgconfig') + subdirs: ['gridfire'], + requires: [ + 'fourdst_composition', + 'fourdst_config', + 'fourdst_constants', + 'fourdst_logging', + ], + extra_cflags: ['-I${includedir}' / 'gridfire' / 'vendor'], ) endif diff --git a/build-python/meson.build b/build-python/meson.build index 74960332..ef857fee 100644 --- a/build-python/meson.build +++ b/build-python/meson.build @@ -1,99 +1,104 @@ if get_option('build_python') - message('Building Python bindings...') + message('Building Python bindings...') - gridfire_py_deps = [ - py_dep, - pybind11_dep, - const_dep, - config_dep, - composition_dep, - gridfire_dep - ] + gridfire_py_deps = [ + py_dep, + pybind11_dep, + gridfire_dep + ] - py_sources = [ - meson.project_source_root() + '/src/python/bindings.cpp', - meson.project_source_root() + '/src/python/types/bindings.cpp', - meson.project_source_root() + '/src/python/partition/bindings.cpp', - meson.project_source_root() + '/src/python/partition/trampoline/py_partition.cpp', - meson.project_source_root() + '/src/python/reaction/bindings.cpp', - meson.project_source_root() + '/src/python/screening/bindings.cpp', - meson.project_source_root() + '/src/python/screening/trampoline/py_screening.cpp', - meson.project_source_root() + '/src/python/io/bindings.cpp', - meson.project_source_root() + '/src/python/io/trampoline/py_io.cpp', - meson.project_source_root() + '/src/python/exceptions/bindings.cpp', - meson.project_source_root() + '/src/python/engine/bindings.cpp', - meson.project_source_root() + '/src/python/engine/trampoline/py_engine.cpp', - meson.project_source_root() + '/src/python/solver/bindings.cpp', - meson.project_source_root() + '/src/python/solver/trampoline/py_solver.cpp', - meson.project_source_root() + '/src/python/policy/bindings.cpp', - meson.project_source_root() + '/src/python/policy/trampoline/py_policy.cpp', - meson.project_source_root() + '/src/python/utils/bindings.cpp', - meson.project_source_root() + '/src/python/config/bindings.cpp', - meson.project_source_root() + '/src/python/engine/scratchpads/bindings.cpp', - ] + if host_machine.system() == 'darwin' + gridfire_ext_rpath = '@loader_path/lib' + else + gridfire_ext_rpath = '$ORIGIN/lib' + endif + + py_sources = [ + meson.project_source_root() + '/src/python/bindings.cpp', + meson.project_source_root() + '/src/python/types/bindings.cpp', + meson.project_source_root() + '/src/python/partition/bindings.cpp', + meson.project_source_root() + '/src/python/partition/trampoline/py_partition.cpp', + meson.project_source_root() + '/src/python/reaction/bindings.cpp', + meson.project_source_root() + '/src/python/screening/bindings.cpp', + meson.project_source_root() + '/src/python/screening/trampoline/py_screening.cpp', + meson.project_source_root() + '/src/python/io/bindings.cpp', + meson.project_source_root() + '/src/python/io/trampoline/py_io.cpp', + meson.project_source_root() + '/src/python/exceptions/bindings.cpp', + meson.project_source_root() + '/src/python/engine/bindings.cpp', + meson.project_source_root() + '/src/python/engine/trampoline/py_engine.cpp', + meson.project_source_root() + '/src/python/solver/bindings.cpp', + meson.project_source_root() + '/src/python/solver/trampoline/py_solver.cpp', + meson.project_source_root() + '/src/python/policy/bindings.cpp', + meson.project_source_root() + '/src/python/policy/trampoline/py_policy.cpp', + meson.project_source_root() + '/src/python/utils/bindings.cpp', + meson.project_source_root() + '/src/python/config/bindings.cpp', + meson.project_source_root() + '/src/python/engine/scratchpads/bindings.cpp', + ] - if meson.is_cross_build() and host_machine.system() == 'darwin' - py_mod = shared_module( - '_gridfire', - sources: py_sources, - dependencies: gridfire_py_deps, - name_prefix: '', - name_suffix: 'so', - install: true, - install_dir: py_installation.get_install_dir() + '/gridfire' - ) - else - py_mod = py_installation.extension_module( - '_gridfire', # Name of the generated .so/.pyd file (without extension) - sources: py_sources, - dependencies : gridfire_py_deps, - install : true, + if meson.is_cross_build() and host_machine.system() == 'darwin' + py_mod = shared_module( + '_gridfire', + sources: py_sources, + dependencies: gridfire_py_deps, + name_prefix: '', + name_suffix: 'so', + install: true, + install_rpath: gridfire_ext_rpath, + install_dir: py_installation.get_install_dir() + '/gridfire' + ) + else + py_mod = py_installation.extension_module( + '_gridfire', + sources: py_sources, + dependencies : gridfire_py_deps, + install : true, + install_rpath: gridfire_ext_rpath, + subdir: 'gridfire', + ) + endif + + + py_installation.install_sources( + files( + meson.project_source_root() + '/src/python/gridfire/__init__.py', + meson.project_source_root() + '/stubs/gridfire/_gridfire/__init__.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/config.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/exceptions.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/partition.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/reaction.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/screening.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/io.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/solver.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/policy.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/type.pyi' + ), subdir: 'gridfire', ) - endif + py_installation.install_sources( + files( + meson.project_source_root() + '/stubs/gridfire/_gridfire/engine/__init__.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/engine/diagnostics.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/engine/scratchpads.pyi' + ), + subdir: 'gridfire/engine', + ) - py_installation.install_sources( - files( - meson.project_source_root() + '/src/python/gridfire/__init__.py', - meson.project_source_root() + '/stubs/gridfire/_gridfire/__init__.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/config.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/exceptions.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/partition.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/reaction.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/screening.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/io.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/solver.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/policy.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/type.pyi' - ), - subdir: 'gridfire', - ) + py_installation.install_sources( + files( + meson.project_source_root() + '/stubs/gridfire/_gridfire/utils/__init__.pyi', + ), + subdir: 'gridfire/utils', + ) - py_installation.install_sources( - files( - meson.project_source_root() + '/stubs/gridfire/_gridfire/engine/__init__.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/engine/diagnostics.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/engine/scratchpads.pyi' - ), - subdir: 'gridfire/engine', - ) - - py_installation.install_sources( - files( - meson.project_source_root() + '/stubs/gridfire/_gridfire/utils/__init__.pyi', - ), - subdir: 'gridfire/utils', - ) - - py_installation.install_sources( - files( - meson.project_source_root() + '/stubs/gridfire/_gridfire/utils/hashing/__init__.pyi', - meson.project_source_root() + '/stubs/gridfire/_gridfire/utils/hashing/reaction.pyi', - ), - subdir: 'gridfire/utils/hashing', - ) + py_installation.install_sources( + files( + meson.project_source_root() + '/stubs/gridfire/_gridfire/utils/hashing/__init__.pyi', + meson.project_source_root() + '/stubs/gridfire/_gridfire/utils/hashing/reaction.pyi', + ), + subdir: 'gridfire/utils/hashing', + ) else - message('Python bindings disabled') + message('Python bindings disabled') endif diff --git a/meson_options.txt b/meson_options.txt index 0d7a71d1..ddde5662 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,4 @@ -option('log_level', type: 'combo', choices: ['traceL3', 'traceL2', 'traceL1', 'debug', 'info', 'warning', 'error', 'critial'], value: 'info', description: 'Set the log level for the GridFire library') +option('log_level', type: 'combo', choices: ['traceL3', 'traceL2', 'traceL1', 'debug', 'info', 'warning', 'error', 'critical'], value: 'info', description: 'Set the log level for the GridFire library') option('pkg_config', type: 'boolean', value: true, description: 'generate pkg-config file for GridFire (gridfire.pc)') option('build_python', type: 'boolean', value: false, description: 'build the python bindings so you can use GridFire from python') option('build_tests', type: 'boolean', value: true, description: 'build the test suite') @@ -12,4 +12,4 @@ option('build_tools', type: 'boolean', value: true, description: 'build the Grid option('openmp_support', type: 'boolean', value: false, description: 'Enable OpenMP support for parallelization') option('use_mimalloc', type: 'boolean', value: true, description: 'Use mimalloc as the memory allocator for GridFire. Generally this is ~10% faster than the system allocator.') option('build_benchmarks', type: 'boolean', value: false, description: 'build the benchmark suite') -option('asan', type: 'boolean', value: false, description: 'Enable AddressSanitizer (ASan) support for detecting memory errors') \ No newline at end of file +option('asan', type: 'boolean', value: false, description: 'Enable AddressSanitizer (ASan) support for detecting memory errors') diff --git a/pip_install_mac_patch.sh b/pip_install_mac_patch.sh index 66491797..151f4a2f 100755 --- a/pip_install_mac_patch.sh +++ b/pip_install_mac_patch.sh @@ -1,5 +1,5 @@ #!/bin/bash -# pip_install_mac.sh - Temporary workaround for meson-python duplicate RPATH bug on macOS +# pip_install_mac_patch.sh - Workaround for meson-python duplicate RPATH bug on macOS set -e @@ -9,26 +9,30 @@ YELLOW='\033[1;33m' GREEN='\033[0;32m' NC='\033[0m' # No Color +# Returns 0 if the Mach-O binary at $1 has duplicate LC_RPATH entries. +has_duplicate_rpaths() { + local binary="$1" + local rpaths dup + rpaths=$(otool -l "$binary" | awk '/cmd LC_RPATH/{getline; getline; print $2}') + dup=$(printf '%s\n' "$rpaths" | sort | uniq -d) + [ -n "$dup" ] +} + echo -e "${YELLOW}" echo "=========================================================================" -echo " TEMPORARY INSTALLATION WORKAROUND" +echo " INSTALLATION + DUPLICATE-RPATH SAFETY NET (macOS)" echo "=========================================================================" echo -e "${NC}" echo "" -echo -e "${YELLOW}WARNING:${NC} This script applies a temporary patch to fix a known issue with" -echo "meson-python that causes duplicate RPATH entries in built Python extensions" -echo "on macOS, preventing module imports." +echo "This script installs gridfire with pip and then checks the installed" +echo "extension modules for duplicate LC_RPATH entries (a meson-python bug" +echo "exposed by macOS 26.1, see:" +echo " https://github.com/mesonbuild/meson-python/issues/813 )." echo "" -echo "This workaround will:" -echo " 1. Install fourdst using pip" -echo " 2. Locate the installed extension module" -echo " 3. Remove duplicate RPATH entries using install_name_tool" +echo "With the current self-contained wheel layout the bug should not" +echo "trigger; binaries are only patched if duplicates are actually found." echo "" -echo "This is a temporary solution while the meson-python team resolves the" -echo "duplicate RPATH bug. For more information, see:" -echo " https://github.com/mesonbuild/meson-python/issues/813" -echo "" -echo -e "${YELLOW}Do you understand and wish to continue? [y/N]${NC} " +echo -e "${YELLOW}Continue? [y/N]${NC} " read -r response if [[ ! "$response" =~ ^[Yy]$ ]]; then @@ -39,7 +43,6 @@ fi echo "" echo -e "${GREEN}Step 1: Finding current Python environment...${NC}" -# Get the current Python executable PYTHON_BIN=$(which python3) if [ -z "$PYTHON_BIN" ]; then echo -e "${RED}Error: python3 not found in PATH${NC}" @@ -50,12 +53,11 @@ echo "Using Python: $PYTHON_BIN" PYTHON_VERSION=$($PYTHON_BIN --version) echo "Python version: $PYTHON_VERSION" -# Get site-packages directory SITE_PACKAGES=$($PYTHON_BIN -c "import site; print(site.getsitepackages()[0])") echo "Site packages: $SITE_PACKAGES" echo "" -echo -e "${GREEN}Step 2: Installing fourdst with pip...${NC}" +echo -e "${GREEN}Step 2: Installing gridfire with pip...${NC}" $PYTHON_BIN -m pip install . -v --no-build-isolation if [ $? -ne 0 ]; then @@ -64,80 +66,43 @@ if [ $? -ne 0 ]; then fi echo "" -echo -e "${GREEN}Step 3: Locating installed gridfire extension module...${NC}" - -# Find the .so file -SO_FILE=$(find "$SITE_PACKAGES/gridfire" -name "_gridfire.cpython-*-darwin.so" 2>/dev/null | head -n 1) - -if [ -z "$SO_FILE" ]; then - echo -e "${RED}Error: Could not find _gridfire.cpython-*-darwin.so in $SITE_PACKAGES/gridfire${NC}" - echo "Installation may have failed or the file is in an unexpected location." - exit 1 -fi - -echo "Found gridfire extension module: $SO_FILE" -echo "" - -echo -e "${GREEN}Step 4: Running RPATH fix script for gridfire extension module...${NC}" - -# Check if fix_rpath.py exists FIX_SCRIPT="build-python/fix_rpaths.py" -if [ ! -f "$FIX_SCRIPT" ]; then - echo -e "${RED}Error: $FIX_SCRIPT not found${NC}" - echo "Please ensure you're running this script from the project root directory." - exit 1 -fi -# Run the fix script -$PYTHON_BIN "$FIX_SCRIPT" "$SO_FILE" +check_and_fix() { + local label="$1" so_file="$2" -if [ $? -ne 0 ]; then - echo -e "${RED}Error: RPATH fix script failed for gridfire extension module${NC}" - exit 1 -fi + if [ -z "$so_file" ]; then + echo -e "${YELLOW}Skipping ${label}: extension module not found (package may not be installed).${NC}" + return 0 + fi -echo -e "${GREEN}Step 5: Locating installed fourdst extension module...${NC}" + echo "Found ${label} extension module: $so_file" + if has_duplicate_rpaths "$so_file"; then + echo -e "${YELLOW}Duplicate LC_RPATH entries detected in ${label}; applying fix...${NC}" + if [ ! -f "$FIX_SCRIPT" ]; then + echo -e "${RED}Error: $FIX_SCRIPT not found${NC}" + echo "Please run this script from the project root directory." + exit 1 + fi + $PYTHON_BIN "$FIX_SCRIPT" "$so_file" + else + echo -e "${GREEN}No duplicate LC_RPATH entries in ${label}; no patch needed.${NC}" + fi + echo "" +} -# Find the .so file -SO_FILE=$(find "$SITE_PACKAGES/fourdst" -name "_phys.cpython-*-darwin.so" 2>/dev/null | head -n 1) +echo -e "${GREEN}Step 3: Checking installed extension modules...${NC}" -if [ -z "$SO_FILE" ]; then - echo -e "${RED}Error: Could not find _phys.cpython-*-darwin.so in $SITE_PACKAGES/fourdst${NC}" - echo "Installation may have failed or the file is in an unexpected location." - exit 1 -fi +GRIDFIRE_SO=$(find "$SITE_PACKAGES/gridfire" -name "_gridfire.cpython-*-darwin.so" 2>/dev/null | head -n 1) +check_and_fix "gridfire" "$GRIDFIRE_SO" -echo "Found fourdst extension module: $SO_FILE" -echo "" +FOURDST_SO=$(find "$SITE_PACKAGES/fourdst" -name "_phys.cpython-*-darwin.so" 2>/dev/null | head -n 1) +check_and_fix "fourdst" "$FOURDST_SO" -echo -e "${GREEN}Step 6: Running RPATH fix script for fourdst extension module...${NC}" - -# Check if fix_rpath.py exists -FIX_SCRIPT="build-python/fix_rpaths.py" -if [ ! -f "$FIX_SCRIPT" ]; then - echo -e "${RED}Error: $FIX_SCRIPT not found${NC}" - echo "Please ensure you're running this script from the project root directory." - exit 1 -fi - -# Run the fix script -$PYTHON_BIN "$FIX_SCRIPT" "$SO_FILE" - -if [ $? -ne 0 ]; then - echo -e "${RED}Error: RPATH fix script failed for fourdst extension module${NC}" - exit 1 -fi - -echo "" echo -e "${GREEN}=========================================================================${NC}" echo -e "${GREEN} Installation Complete!${NC}" echo -e "${GREEN}=========================================================================${NC}" echo "" -echo "You can now use fourdst in your Python environment." -echo "" echo "Test the installation with:" echo " $PYTHON_BIN -c 'import gridfire; print(gridfire.__version__)'" echo "" -echo -e "${YELLOW}Note:${NC} If you reinstall or upgrade fourdst, you will need to run this" -echo "script again to apply the RPATH fix." -echo "" \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index b14c2506..fc2e428f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,17 @@ [build-system] requires = [ - "meson-python>=0.15.0", # Use a recent version - "meson==1.9.1", # Specify your Meson version requirement - "pybind11>=2.10" # pybind11 headers needed at build time + "meson-python>=0.19.0", + "meson>=1.9.1", + "pybind11>=2.10" ] build-backend = "mesonpy" [project] -name = "gridfire" # Choose your Python package name -version = "v0.7.6rc4.2" # Your project's version +name = "gridfire" +version = "v0.7.6rc4.2" description = "Python interface to the GridFire nuclear network code" readme = "README.md" -license = { file = "LICENSE.txt" } # Reference your license file [cite: 2] +license = { file = "LICENSE.txt" } authors = [ {name = "Emily M. Boudreaux", email = "emily@boudreauxmail.com"}, @@ -22,4 +22,20 @@ maintainers = [ ] [tool.meson-python.args] -setup = ['-Dpkg_config=false', '-Dbuildtype=release', '-Dopenmp_support=true', '-Dasan=false', '-Dlog_level=error', '-Dbuild_tests=false', '-Dbuild_c_api=false', '-Dbuild_examples=false', '-Dbuild_benchmarks=false', '-Dbuild_tools=false', '-Dplugin_support=false', '-Duse_mimalloc=false', '-Dbuild_python=true'] +setup = [ + '-Ddefault_library=static', + '-Dpkg_config=false', + '-Dbuildtype=release', + '-Dopenmp_support=true', + '-Dasan=false', + '-Dlog_level=error', + '-Dbuild_tests=false', + '-Dbuild_c_api=false', + '-Dbuild_examples=false', + '-Dbuild_benchmarks=false', + '-Dbuild_tools=false', + '-Dplugin_support=false', + '-Duse_mimalloc=false', + '-Dbuild_python=true' +] +install = ['--skip-subprojects'] diff --git a/src/include/gridfire/engine/engine_graph.h b/src/include/gridfire/engine/engine_graph.h index 67743284..2891ab9a 100644 --- a/src/include/gridfire/engine/engine_graph.h +++ b/src/include/gridfire/engine/engine_graph.h @@ -16,8 +16,6 @@ #include "gridfire/engine/scratchpads/blob.h" -#include "ankerl/unordered_dense.h" - #include #include #include diff --git a/src/include/gridfire/solver/strategies/PointSolver.h b/src/include/gridfire/solver/strategies/PointSolver.h index 55da9ec6..2ae2a243 100644 --- a/src/include/gridfire/solver/strategies/PointSolver.h +++ b/src/include/gridfire/solver/strategies/PointSolver.h @@ -15,6 +15,8 @@ #include #include #include +#include +#include // SUNDIALS/CVODE headers #include @@ -80,6 +82,24 @@ namespace gridfire::solver { [[nodiscard]] std::vector> describe() const override; [[nodiscard]] fourdst::composition::Composition getPhysicalComposition() const; + + /** + * @brief Zero-copy view of the raw solver state vector. + * + * Layout: [y_0, ..., y_{N-1}, eps] where y_i are molar abundances in + * networkSpecies order and eps is the accumulated specific energy. + * The view is only valid for the duration of the callback. + */ + [[nodiscard]] std::span rawState() const; + + /// Abundance of the species at @p species_index (solver state indexing). + [[nodiscard]] double abundance(size_t species_index) const; + + /// Abundance of @p sp, or std::nullopt if it is not in the active network. + [[nodiscard]] std::optional abundance(const fourdst::atomic::Species& sp) const; + + /// Accumulated specific energy [erg/g] (the trailing state entry). + [[nodiscard]] double accumulatedSpecificEnergy() const; }; using TimestepCallback = std::function; ///< Type alias for a timestep callback function. diff --git a/src/include/gridfire/utils/meson.build b/src/include/gridfire/utils/meson.build index f013464e..ad6a824d 100644 --- a/src/include/gridfire/utils/meson.build +++ b/src/include/gridfire/utils/meson.build @@ -26,16 +26,10 @@ message(' Minor: ' + ver_parts[1]) message(' Patch: ' + ver_parts[2]) message(' Tag: ' + ver_parts[3]) -do_install_version_file = true -if get_option('build_python') - message('Not installing version file since we are building the Python extension. The version information will be included in the Python module instead.') - do_install_version_file = false -endif - configure_file( input : 'config.h.in', output : 'config.h', configuration : conf_data, - install : do_install_version_file, - install_dir : get_option('includedir') / 'gridfire/utils' -) \ No newline at end of file + install : true, + install_dir : gridfire_includedir / 'gridfire/utils' +) diff --git a/src/lib/engine/procedures/priming.cpp b/src/lib/engine/procedures/priming.cpp index 547f1630..08c89fa1 100644 --- a/src/lib/engine/procedures/priming.cpp +++ b/src/lib/engine/procedures/priming.cpp @@ -1,7 +1,7 @@ #include "gridfire/engine/procedures/priming.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "gridfire/solver/solver.h" #include "gridfire/engine/engine_abstract.h" diff --git a/src/lib/policy/stellar_policy.cpp b/src/lib/policy/stellar_policy.cpp index c7400ce9..3a0457c3 100644 --- a/src/lib/policy/stellar_policy.cpp +++ b/src/lib/policy/stellar_policy.cpp @@ -14,7 +14,7 @@ #include "gridfire/engine/scratchpads/engine_multiscale_scratchpad.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" namespace { std::set initialize_seed_species() { diff --git a/src/lib/solver/strategies/PointSolver.cpp b/src/lib/solver/strategies/PointSolver.cpp index 8fceee8e..29efd6da 100644 --- a/src/lib/solver/strategies/PointSolver.cpp +++ b/src/lib/solver/strategies/PointSolver.cpp @@ -88,6 +88,28 @@ namespace gridfire::solver { return engine.collectComposition(state_ctx, base_comp, T9, rho); } + static_assert(std::is_same_v, "PointSolverTimestepContext accessors assume SUNDIALS is built with double precision"); + std::span PointSolverTimestepContext::rawState() const { + return { N_VGetArrayPointer(state), + static_cast(N_VGetLength(state)) }; + } + + double PointSolverTimestepContext::abundance(const size_t species_index) const { + return N_VGetArrayPointer(state)[species_index]; + } + + std::optional PointSolverTimestepContext::abundance(const fourdst::atomic::Species& sp) const { + const auto& species = engine.getNetworkSpecies(state_ctx); + if (std::ranges::find(species, sp) == species.end()) { + return std::nullopt; + } + return abundance(engine.getSpeciesIndex(state_ctx, sp)); + } + + double PointSolverTimestepContext::accumulatedSpecificEnergy() const { + return N_VGetArrayPointer(state)[networkSpecies.size()]; + } + void PointSolverContext::init() { reset_all(); init_context(); diff --git a/src/meson.build b/src/meson.build index 0f4439c4..e9b89811 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,6 @@ -# Define the library -subdir('include/gridfire/utils') # Generate the version header file first +subdir('include/gridfire/utils') + +cpp = meson.get_compiler('cpp') gridfire_sources = files( 'lib/engine/engine_graph.cpp', @@ -44,7 +45,6 @@ gridfire_build_dependencies = [ eigen_dep, sundials_dep, json_dep, - uod_dep, ] if get_option('use_mimalloc') @@ -60,40 +60,70 @@ if get_option('openmp_support') gridfire_build_dependencies += [openmp_dep] endif -# Define the libnetwork library so it can be linked against by other parts of the build system +gridfire_link_whole = [libcvode_static, libkinsol_static, libcppad_static] + +gridfire_link_args = cpp.get_supported_link_arguments( + '-Wl,--exclude-libs,libcvode-static.a:libkinsol_static.a' +) + if get_option('build_python') - libgridfire = static_library('gridfire', - gridfire_sources, - include_directories: include_directories('include'), - dependencies: gridfire_build_dependencies, - cpp_args: gridfire_args, - objects: [cvode_objs, kinsol_objs], - install : false) + gridfire_link_whole += [libcomposition, libconst, liblogging] + if get_option('plugin_support') + gridfire_link_whole += [libplugin] + endif + libgridfire = shared_library('gridfire', + gridfire_sources, + include_directories: include_directories('include'), + dependencies: gridfire_build_dependencies, + cpp_args: gridfire_args, + link_whole: gridfire_link_whole, + link_args: gridfire_link_args, + install: true, + install_dir: gridfire_libdir) else libgridfire = library('gridfire', gridfire_sources, include_directories: include_directories('include'), dependencies: gridfire_build_dependencies, - objects: [cvode_objs, kinsol_objs], + link_whole: gridfire_link_whole, + link_args: gridfire_link_args, cpp_args: gridfire_args, install : true) endif -gridfire_dep = declare_dependency( - include_directories: include_directories('include'), - link_with: libgridfire, - sources: gridfire_sources, - dependencies: gridfire_build_dependencies, - compile_args: gridfire_args, -) +if get_option('build_python') + gridfire_iface_deps = [] + foreach d : gridfire_build_dependencies + gridfire_iface_deps += d.partial_dependency(compile_args: true, includes: true) + endforeach + gridfire_dep = declare_dependency( + include_directories: include_directories('include'), + link_with: libgridfire, + dependencies: gridfire_iface_deps, + compile_args: gridfire_args, + ) +else + gridfire_dep = declare_dependency( + include_directories: include_directories('include'), + link_with: libgridfire, + dependencies: gridfire_build_dependencies, + compile_args: gridfire_args, + ) +endif -install_subdir('include/gridfire', install_dir: get_option('includedir')) +meson.override_dependency('gridfire', gridfire_dep) + +install_subdir('include/gridfire', + install_dir: gridfire_includedir, + exclude_files: ['utils/config.h.in'], +) if not get_option('build_c_api') and get_option('build_fortran') - error('Cannot build fortran without C API. Set -Dbuild-c-api=true and -Dbuild-fortran=true') + error('Cannot build fortran without C API. Set -Dbuild-c-api=true and -Dbuild-fortran=true') endif if get_option('build_c_api') - message('Configuring C API...') - subdir('extern') + message('Configuring C API...') + subdir('extern') endif + diff --git a/subprojects/fourdst.wrap b/subprojects/fourdst.wrap index 6e9da7d4..4e51846c 100644 --- a/subprojects/fourdst.wrap +++ b/subprojects/fourdst.wrap @@ -1,4 +1,4 @@ [wrap-git] url = https://github.com/4D-STAR/fourdst -revision = v0.9.22 +revision = v0.10.1 depth = 1 diff --git a/tests/graphnet_sandbox/main.cpp b/tests/graphnet_sandbox/main.cpp index ade7d44b..93c67bdd 100644 --- a/tests/graphnet_sandbox/main.cpp +++ b/tests/graphnet_sandbox/main.cpp @@ -9,7 +9,7 @@ #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" diff --git a/tools/gf_bbn/main.cpp b/tools/gf_bbn/main.cpp index 19242b92..7cbe72a3 100644 --- a/tools/gf_bbn/main.cpp +++ b/tools/gf_bbn/main.cpp @@ -10,7 +10,7 @@ #include "fourdst/composition/composition.h" #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" @@ -156,8 +156,8 @@ void record_abundance_history_callback(const gridfire::solver::PointSolverTimest std::vector Y; for (const auto& species : engine.getNetworkSpecies(ctx.state_ctx)) { const size_t sid = engine.getSpeciesIndex(ctx.state_ctx, species); - double y = N_VGetArrayPointer(ctx.state)[sid]; - Y.push_back(y > 0.0 ? y : 0.0); // Regularize tiny negative abundances to zero + const double y = ctx.abundance(sid); + Y.push_back(y > 0.0 ? y : 0.0); } const fourdst::composition::Composition comp(engine.getNetworkSpecies(ctx.state_ctx), Y); diff --git a/tools/gf_multi/main.cpp b/tools/gf_multi/main.cpp index 41aa2e51..6ef954e3 100644 --- a/tools/gf_multi/main.cpp +++ b/tools/gf_multi/main.cpp @@ -11,7 +11,7 @@ #include "fourdst/composition/composition.h" #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" @@ -226,14 +226,12 @@ void log_results(const gridfire::NetOut& netOut, const gridfire::NetIn& netIn) { void record_abundance_history_callback(const gridfire::solver::PointSolverTimestepContext& ctx) { s_wrote_abundance_history = true; const auto& engine = ctx.engine; - // std::unordered_map> abundances; std::vector Y; for (const auto& species : engine.getNetworkSpecies(ctx.state_ctx)) { const size_t sid = engine.getSpeciesIndex(ctx.state_ctx, species); - double y = N_VGetArrayPointer(ctx.state)[sid]; - Y.push_back(y > 0.0 ? y : 0.0); // Regularize tiny negative abundances to zero + const double y = ctx.abundance(sid); + Y.push_back(y > 0.0 ? y : 0.0); } - fourdst::composition::Composition comp(engine.getNetworkSpecies(ctx.state_ctx), Y); diff --git a/tools/gf_quick/main.cpp b/tools/gf_quick/main.cpp index ae5d9b58..b7ee8afd 100644 --- a/tools/gf_quick/main.cpp +++ b/tools/gf_quick/main.cpp @@ -11,7 +11,7 @@ #include "fourdst/composition/composition.h" #include "fourdst/logging/logging.h" #include "fourdst/atomic/species.h" -#include "fourdst/composition/utils.h" +#include "fourdst/composition/utils/utils.h" #include "quill/Logger.h" #include "quill/Backend.h" @@ -157,10 +157,9 @@ void record_abundance_history_callback(const gridfire::solver::PointSolverTimest std::vector Y; for (const auto& species : engine.getNetworkSpecies(ctx.state_ctx)) { const size_t sid = engine.getSpeciesIndex(ctx.state_ctx, species); - double y = N_VGetArrayPointer(ctx.state)[sid]; - Y.push_back(y > 0.0 ? y : 0.0); // Regularize tiny negative abundances to zero + const double y = ctx.abundance(sid); + Y.push_back(y > 0.0 ? y : 0.0); } - const fourdst::composition::Composition comp(engine.getNetworkSpecies(ctx.state_ctx), Y); IntermediateResult stepResult; stepResult.comp = comp;