build(meson): much more robust build system

This commit is contained in:
2026-06-10 14:28:55 -04:00
parent 1c975a873d
commit d6fff3cdbe
33 changed files with 571 additions and 360 deletions

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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,
)

View File

@@ -1,5 +1,13 @@
eigen_dep = dependency(
'eigen3',
version : '>=3.3',
fallback : ['eigen', 'eigen_dep']
).as_system()
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,
)

View File

@@ -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

View File

@@ -1,3 +1,9 @@
json_dep = declare_dependency(
include_directories: include_directories('include')
)
install_subdir(
'include',
install_dir: gridfire_vendor_includedir,
strip_directory: true,
)

View File

@@ -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')

View File

@@ -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)

View File

@@ -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,
)

View File

@@ -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
)

View File

@@ -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 <sundials/...> 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 <mpi.h>).
subdir('vendor')

View File

@@ -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',
)

View File

@@ -1,4 +1,9 @@
xxhash_dep = declare_dependency(
include_directories: include_directories('include')
)
install_subdir(
'include',
install_dir: gridfire_vendor_includedir,
strip_directory: true,
)

View File

@@ -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}

View File

@@ -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

View File

@@ -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

View File

@@ -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')
option('asan', type: 'boolean', value: false, description: 'Enable AddressSanitizer (ASan) support for detecting memory errors')

View File

@@ -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 ""

View File

@@ -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']

View File

@@ -16,8 +16,6 @@
#include "gridfire/engine/scratchpads/blob.h"
#include "ankerl/unordered_dense.h"
#include <string>
#include <unordered_map>
#include <vector>

View File

@@ -15,6 +15,8 @@
#include <string>
#include <vector>
#include <tuple>
#include <span>
#include <optional>
// SUNDIALS/CVODE headers
#include <cvode/cvode.h>
@@ -80,6 +82,24 @@ namespace gridfire::solver {
[[nodiscard]] std::vector<std::tuple<std::string, std::string>> 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<const double> 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<double> abundance(const fourdst::atomic::Species& sp) const;
/// Accumulated specific energy [erg/g] (the trailing state entry).
[[nodiscard]] double accumulatedSpecificEnergy() const;
};
using TimestepCallback = std::function<void(const PointSolverTimestepContext& context)>; ///< Type alias for a timestep callback function.

View File

@@ -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'
)
install : true,
install_dir : gridfire_includedir / 'gridfire/utils'
)

View File

@@ -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"

View File

@@ -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<fourdst::atomic::Species> initialize_seed_species() {

View File

@@ -88,6 +88,28 @@ namespace gridfire::solver {
return engine.collectComposition(state_ctx, base_comp, T9, rho);
}
static_assert(std::is_same_v<sunrealtype, double>, "PointSolverTimestepContext accessors assume SUNDIALS is built with double precision");
std::span<const double> PointSolverTimestepContext::rawState() const {
return { N_VGetArrayPointer(state),
static_cast<std::size_t>(N_VGetLength(state)) };
}
double PointSolverTimestepContext::abundance(const size_t species_index) const {
return N_VGetArrayPointer(state)[species_index];
}
std::optional<double> 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();

View File

@@ -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

View File

@@ -1,4 +1,4 @@
[wrap-git]
url = https://github.com/4D-STAR/fourdst
revision = v0.9.22
revision = v0.10.1
depth = 1

View File

@@ -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"

View File

@@ -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<double> 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);

View File

@@ -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<std::string, std::pair<double, double>> abundances;
std::vector<double> 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);

View File

@@ -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<double> 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;