fix(gcc): Fixed Gridfire on gcc

GridFire failed to compile on gcc and gnu stdlibc++ this has been
resolved. Further, the boost dependency has been removed since we no
longer use boost at all. This should dramatically simplify installation.
Finally we have added some build system checks to ensure that the
correct version of a C++ and fortran compiler are present on the system
This commit is contained in:
2025-11-28 09:42:54 -05:00
parent 08a031f30c
commit 033c5a083d
11 changed files with 42 additions and 67 deletions

4
.gitignore vendored
View File

@@ -77,10 +77,11 @@ subprojects/liblogging/
subprojects/eigen-*/ subprojects/eigen-*/
subprojects/fourdst/ subprojects/fourdst/
subprojects/libplugin/ subprojects/libplugin/
subprojects/minizip-ng-4.0.10/ subprojects/minizip-ng-*/
subprojects/cvode-*/ subprojects/cvode-*/
subprojects/kinsol-*/ subprojects/kinsol-*/
subprojects/CLI11-*/ subprojects/CLI11-*/
subprojects/openssl-*/
*.fbundle *.fbundle
*.wraplock *.wraplock
@@ -95,6 +96,7 @@ libconfig.wrap
libconstants.wrap libconstants.wrap
liblogging.wrap liblogging.wrap
minizip-ng.wrap minizip-ng.wrap
openssl.wrap
.vscode/ .vscode/

View File

@@ -5,7 +5,6 @@ subdir('libplugin')
subdir('sundials') subdir('sundials')
subdir('boost')
subdir('cppad') subdir('cppad')
subdir('xxHash') subdir('xxHash')
subdir('eigen') subdir('eigen')

View File

@@ -39,12 +39,34 @@ if meson.get_compiler('cpp').get_id() == 'gcc'
# We disable these because of boost notes about abi changes from C++10 -> C++17 make the build too noisey # We disable these because of boost notes about abi changes from C++10 -> C++17 make the build too noisey
message('disabling psabi warnings for gcc') message('disabling psabi warnings for gcc')
add_project_arguments('-Wno-psabi', language: 'cpp') add_project_arguments('-Wno-psabi', language: 'cpp')
if (meson.get_compiler('cpp').version().version_compare('<14.0'))
error('g++ version must be at least 14.0, found ' + meson.get_compiler('cpp').version())
endif
endif
build_fortran = get_option('build-fortran')
if (build_fortran)
add_languages('fortran', native: true)
message('Building fortran module (gridfire_mod.mod)')
fc = meson.get_compiler('fortran')
if not get_option('unsafe-fortran')
if fc.get_id() != 'gcc'
error('The only supported fortran compiler for GridFire is gfortran (version >= 14.0), found ' + fc + '. GridFire has not been tested with any other compilers. You can disable this check with the -Dunsafe-fortran=true flag to try other compilers')
endif
endif
endif
if (meson.get_compiler('fortran').version().version_compare('<14.0'))
error('gfortran version must be at least 14.0, found ' + meson.get_compiler('fortran').version())
endif endif
# For Eigen # For Eigen
add_project_arguments('-Wno-deprecated-declarations', language: 'cpp') add_project_arguments('-Wno-deprecated-declarations', language: 'cpp')
llevel = get_option('log_level') llevel = get_option('log-level')
logbase='QUILL_COMPILE_ACTIVE_LOG_LEVEL_' logbase='QUILL_COMPILE_ACTIVE_LOG_LEVEL_'

View File

@@ -1,4 +1,6 @@
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', 'critial'], 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('pkg-config', type: 'boolean', value: true, description: 'generate pkg-config file for GridFire (gridfire.pc)')
option('build-python', type: 'boolean', value: true, description: 'build the python bindings so you can use GridFire from python') option('build-python', type: 'boolean', value: true, description: 'build the python bindings so you can use GridFire from python')
option('build-tests', type: 'boolean', value: true, description: 'build the test suite') option('build-tests', type: 'boolean', value: true, description: 'build the test suite')
option('build-fortran', type: 'boolean', value: true, description: 'build fortran module support')
option('unsafe-fortran', type: 'boolean', value: false, description: 'Allow untested fortran compilers (compilers other than gfortran)')

View File

@@ -20,7 +20,6 @@
#include <ranges> #include <ranges>
#include <functional> #include <functional>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include "cppad/cppad.hpp" #include "cppad/cppad.hpp"
#include "cppad/utility/sparse_rc.hpp" #include "cppad/utility/sparse_rc.hpp"
@@ -863,7 +862,6 @@ namespace gridfire::engine {
std::unordered_map<fourdst::atomic::Species, size_t> m_speciesToIndexMap; ///< Map from species to their index in the stoichiometry matrix. std::unordered_map<fourdst::atomic::Species, size_t> m_speciesToIndexMap; ///< Map from species to their index in the stoichiometry matrix.
std::unordered_map<size_t, fourdst::atomic::Species> m_indexToSpeciesMap; ///< Map from index to species in the stoichiometry matrix. std::unordered_map<size_t, fourdst::atomic::Species> m_indexToSpeciesMap; ///< Map from index to species in the stoichiometry matrix.
boost::numeric::ublas::compressed_matrix<int> m_stoichiometryMatrix; ///< Stoichiometry matrix (species x reactions).
mutable CppAD::ADFun<double> m_rhsADFun; ///< CppAD function for the right-hand side of the ODE. mutable CppAD::ADFun<double> m_rhsADFun; ///< CppAD function for the right-hand side of the ODE.
mutable CppAD::ADFun<double> m_epsADFun; ///< CppAD function for the energy generation rate. mutable CppAD::ADFun<double> m_epsADFun; ///< CppAD function for the energy generation rate.
@@ -1281,4 +1279,4 @@ namespace gridfire::engine {
return molar_concentration_product * k_reaction * densityTerm; return molar_concentration_product * k_reaction * densityTerm;
} }
}; };

View File

@@ -24,9 +24,6 @@
#include <fstream> #include <fstream>
#include <ranges> #include <ranges>
#include <boost/numeric/odeint.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include "cppad/cppad.hpp" #include "cppad/cppad.hpp"
#include "cppad/utility/sparse_rc.hpp" #include "cppad/utility/sparse_rc.hpp"
#include "cppad/utility/sparse_rcv.hpp" #include "cppad/utility/sparse_rcv.hpp"
@@ -819,9 +816,9 @@ namespace gridfire::engine {
LOG_TRACE_L1(m_logger, "Generating stoichiometry matrix..."); LOG_TRACE_L1(m_logger, "Generating stoichiometry matrix...");
// Task 1: Set dimensions and initialize the matrix // Task 1: Set dimensions and initialize the matrix
size_t numSpecies = m_networkSpecies.size(); // size_t numSpecies = m_networkSpecies.size();
size_t numReactions = m_reactions.size(); // size_t numReactions = m_reactions.size();
m_stoichiometryMatrix.resize(numSpecies, numReactions, false); // m_stoichiometryMatrix.resize(numSpecies, numReactions, false);
LOG_TRACE_L1(m_logger, "Stoichiometry matrix initialized with dimensions: {} rows (species) x {} columns (reactions).", LOG_TRACE_L1(m_logger, "Stoichiometry matrix initialized with dimensions: {} rows (species) x {} columns (reactions).",
numSpecies, numReactions); numSpecies, numReactions);
@@ -838,9 +835,9 @@ namespace gridfire::engine {
// Find the row index for this species // Find the row index for this species
auto it = m_speciesToIndexMap.find(species); auto it = m_speciesToIndexMap.find(species);
if (it != m_speciesToIndexMap.end()) { if (it != m_speciesToIndexMap.end()) {
const size_t speciesRowIndex = it->second; // const size_t speciesRowIndex = it->second;
// Set the matrix element. Boost.uBLAS handles sparse insertion. // Set the matrix element. Boost.uBLAS handles sparse insertion.
m_stoichiometryMatrix(speciesRowIndex, reactionColumnIndex) = coefficient; // m_stoichiometryMatrix(speciesRowIndex, reactionColumnIndex) = coefficient;
} else { } else {
// This scenario should ideally not happen if m_networkSpeciesMap and m_speciesToIndexMap are correctly synced // This scenario should ideally not happen if m_networkSpeciesMap and m_speciesToIndexMap are correctly synced
LOG_ERROR(m_logger, "CRITICAL ERROR: Species '{}' from reaction '{}' stoichiometry not found in species to index map.", LOG_ERROR(m_logger, "CRITICAL ERROR: Species '{}' from reaction '{}' stoichiometry not found in species to index map.",
@@ -852,8 +849,6 @@ namespace gridfire::engine {
reactionColumnIndex++; // Move to the next column for the next reaction reactionColumnIndex++; // Move to the next column for the next reaction
} }
LOG_TRACE_L1(m_logger, "Stoichiometry matrix population complete. Number of non-zero elements: {}.",
m_stoichiometryMatrix.nnz()); // Assuming nnz() exists for compressed_matrix
} }
void GraphEngine::setScreeningModel(const screening::ScreeningType model) { void GraphEngine::setScreeningModel(const screening::ScreeningType model) {

View File

@@ -15,7 +15,7 @@ namespace gridfire::engine {
const Eigen::SparseMatrix<double>& jacobianMatrix, const Eigen::SparseMatrix<double>& jacobianMatrix,
const std::function<fourdst::atomic::Species(size_t)> &indexToSpeciesFunc const std::function<fourdst::atomic::Species(size_t)> &indexToSpeciesFunc
): m_jacobianMatrix(jacobianMatrix) { ): m_jacobianMatrix(jacobianMatrix) {
for (size_t i = 0; i < jacobianMatrix.rows(); ++i) { for (long int i = 0; i < jacobianMatrix.rows(); ++i) {
fourdst::atomic::Species species = indexToSpeciesFunc(i); fourdst::atomic::Species species = indexToSpeciesFunc(i);
m_speciesToIndexMap[species] = i; m_speciesToIndexMap[species] = i;
} }
@@ -57,7 +57,7 @@ namespace gridfire::engine {
} }
double NetworkJacobian::operator()(const size_t i, const size_t j) const { double NetworkJacobian::operator()(const size_t i, const size_t j) const {
if (i >= m_jacobianMatrix.rows() || j >= m_jacobianMatrix.cols()) { if (i >= static_cast<size_t>(m_jacobianMatrix.rows()) || j >= static_cast<size_t>(m_jacobianMatrix.cols())) {
throw std::out_of_range(std::format("Index ({}, {}) out of bounds in NetworkJacobian operator() for jacobian of shape ({}, {}).", i, j, m_jacobianMatrix.rows(), m_jacobianMatrix.cols())); throw std::out_of_range(std::format("Index ({}, {}) out of bounds in NetworkJacobian operator() for jacobian of shape ({}, {}).", i, j, m_jacobianMatrix.rows(), m_jacobianMatrix.cols()));
} }
return m_jacobianMatrix.coeff(i, j); return m_jacobianMatrix.coeff(i, j);
@@ -73,7 +73,7 @@ namespace gridfire::engine {
} }
void NetworkJacobian::set(const size_t i, const size_t j, const double value) { void NetworkJacobian::set(const size_t i, const size_t j, const double value) {
if (i >= m_jacobianMatrix.rows() || j >= m_jacobianMatrix.cols()) { if (i >= static_cast<size_t>(m_jacobianMatrix.rows()) || j >= static_cast<size_t>(m_jacobianMatrix.cols())) {
throw std::out_of_range(std::format("Index ({}, {}) out of bounds in NetworkJacobian set() for jacobian of shape ({}, {}).", i, j, m_jacobianMatrix.rows(), m_jacobianMatrix.cols())); throw std::out_of_range(std::format("Index ({}, {}) out of bounds in NetworkJacobian set() for jacobian of shape ({}, {}).", i, j, m_jacobianMatrix.rows(), m_jacobianMatrix.cols()));
} }
m_jacobianMatrix.coeffRef(i, j) = value; m_jacobianMatrix.coeffRef(i, j) = value;

View File

@@ -31,7 +31,6 @@ gridfire_sources = files(
gridfire_build_dependencies = [ gridfire_build_dependencies = [
boost_dep,
const_dep, const_dep,
config_dep, config_dep,
composition_dep, composition_dep,
@@ -67,4 +66,4 @@ if get_option('build-python')
subdir('python') subdir('python')
else else
message('Skipping Python bindings...') message('Skipping Python bindings...')
endif endif

View File

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

View File

@@ -1,4 +1,4 @@
[wrap-git] [wrap-git]
url = https://github.com/4D-STAR/libplugin url = https://github.com/4D-STAR/libplugin
revision = v0.3.4 revision = v0.3.5
depth = 1 depth = 1

View File

@@ -15,16 +15,12 @@
#include <clocale> #include <clocale>
#include <boost/json/src.hpp>
#include "gridfire/reaction/reaclib.h" #include "gridfire/reaction/reaclib.h"
static std::terminate_handler g_previousHandler = nullptr; static std::terminate_handler g_previousHandler = nullptr;
boost::json::object g_reaction_contribution_history;
static std::vector<std::pair<double, std::unordered_map<std::string, std::pair<double, double>>>> g_callbackHistory; static std::vector<std::pair<double, std::unordered_map<std::string, std::pair<double, double>>>> g_callbackHistory;
static bool s_wrote_abundance_history = false; static bool s_wrote_abundance_history = false;
static bool s_wrote_reaction_history = false;
void quill_terminate_handler(); void quill_terminate_handler();
gridfire::NetIn init(const double temp, const double rho, const double tMax) { gridfire::NetIn init(const double temp, const double rho, const double tMax) {
@@ -164,37 +160,6 @@ void record_abundance_history_callback(const gridfire::solver::CVODESolverStrate
g_callbackHistory.emplace_back(ctx.t, abundances); g_callbackHistory.emplace_back(ctx.t, abundances);
} }
size_t g_iters = 0;
void record_contribution_callback(const gridfire::solver::CVODESolverStrategy::TimestepContext& ctx) {
s_wrote_reaction_history = true;
boost::json::object timestep;
boost::json::object reaction_contribution;
boost::json::object species_abundance;
std::set<fourdst::atomic::Species> activeSpecies(ctx.engine.getNetworkSpecies().begin(), ctx.engine.getNetworkSpecies().end());
for (const auto& [species, contributions] : ctx.reactionContributionMap) {
boost::json::object species_obj;
for (const auto& [reaction_id, contribution] : contributions) {
species_obj[reaction_id] = contribution;
}
reaction_contribution[std::string(species.name())] = species_obj;
double y;
if (activeSpecies.contains(species)) {
const size_t sid = ctx.engine.getSpeciesIndex(species);
y = N_VGetArrayPointer(ctx.state)[sid];
} else {
y = 0.0;
}
species_abundance[std::string(species.name())] = y;
}
timestep["t"] = ctx.t;
timestep["dt"] = ctx.dt;
timestep["reaction_contribution"] = reaction_contribution;
timestep["species_abundance"] = species_abundance;
g_reaction_contribution_history[std::to_string(g_iters)] = timestep;
g_iters++;
}
void save_callback_data(const std::string_view filename) { void save_callback_data(const std::string_view filename) {
std::set<std::string> unique_species; std::set<std::string> unique_species;
@@ -243,12 +208,6 @@ void log_callback_data(const double temp) {
save_callback_data("abundance_history_" + std::to_string(temp) + ".csv"); save_callback_data("abundance_history_" + std::to_string(temp) + ".csv");
} }
if (s_wrote_reaction_history) {
std::cout << "Saving reaction history to reaction_contribution_history.json" << std::endl;
std::ofstream jsonFile("reaction_contribution_history_" + std::to_string(temp) + ".json", std::ios::out);
jsonFile << boost::json::serialize(g_reaction_contribution_history);
jsonFile.close();
}
} }
void quill_terminate_handler() void quill_terminate_handler()
@@ -263,7 +222,6 @@ void quill_terminate_handler()
void callback_main(const gridfire::solver::CVODESolverStrategy::TimestepContext& ctx) { void callback_main(const gridfire::solver::CVODESolverStrategy::TimestepContext& ctx) {
record_abundance_history_callback(ctx); record_abundance_history_callback(ctx);
record_contribution_callback(ctx);
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
@@ -294,4 +252,4 @@ int main(int argc, char** argv) {
log_results(netOut, netIn); log_results(netOut, netIn);
log_callback_data(temp); log_callback_data(temp);
} }