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

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