feat(weak): major weak rate progress

Major weak rate progress which includes: A refactor of many of the public interfaces for GridFire Engines to use composition objects as opposed to raw abundance vectors. This helps prevent index mismatch errors. Further, the weak reaction class has been expanded with the majority of an implimentation, including an atomic_base derived class to allow for proper auto diff tracking of the interpolated table results. Some additional changes are that the version of fourdst and libcomposition have been bumped to versions with smarter caching of intermediate vectors and a few bug fixes.
This commit is contained in:
2025-10-07 15:16:03 -04:00
parent 4f1c260444
commit 8a0b5b2c36
53 changed files with 2310 additions and 1759 deletions

View File

@@ -19,14 +19,14 @@ namespace gridfire::diagnostics {
void inspect_species_balance(
const DynamicEngine& engine,
const std::string& species_name,
const std::vector<double>& Y_full,
const fourdst::composition::Composition &comp,
double T9,
double rho
);
void inspect_jacobian_stiffness(
const DynamicEngine& engine,
const std::vector<double>& Y_full,
const fourdst::composition::Composition &comp,
double T9,
double rho
);

View File

@@ -58,8 +58,10 @@ namespace gridfire {
*/
template <IsArithmeticOrAD T>
struct StepDerivatives {
std::vector<T> dydt; ///< Derivatives of abundances (dY/dt for each species).
std::map<fourdst::atomic::Species, T> dydt; ///< Derivatives of abundances (dY/dt for each species).
T nuclearEnergyGenerationRate = T(0.0); ///< Specific energy generation rate (e.g., erg/g/s).
StepDerivatives() : dydt(), nuclearEnergyGenerationRate(T(0.0)) {}
};
using SparsityPattern = std::vector<std::pair<size_t, size_t>>;
@@ -107,7 +109,7 @@ namespace gridfire {
/**
* @brief Calculate the right-hand side (dY/dt) and energy generation.
*
* @param Y Vector of current abundances for all species.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return StepDerivatives<double> containing dY/dt and energy generation rate.
@@ -117,7 +119,7 @@ namespace gridfire {
* rate for the current state.
*/
[[nodiscard]] virtual std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const std::vector<double>& Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const = 0;
@@ -142,7 +144,7 @@ namespace gridfire {
/**
* @brief Generate the Jacobian matrix for the current state.
*
* @param Y_dynamic Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
*
@@ -150,13 +152,13 @@ namespace gridfire {
* for the current state. The matrix can then be accessed via getJacobianMatrixEntry().
*/
virtual void generateJacobianMatrix(
const std::vector<double>& Y_dynamic,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const = 0;
virtual void generateJacobianMatrix(
const std::vector<double>& Y_dynamic,
const fourdst::composition::Composition& comp,
double T9,
double rho,
const SparsityPattern& sparsityPattern
@@ -167,15 +169,15 @@ namespace gridfire {
/**
* @brief Get an entry from the previously generated Jacobian matrix.
*
* @param i Row index (species index).
* @param j Column index (species index).
* @param rowSpecies The species corresponding to the row index (i)
* @param colSpecies The species corresponding to the column index (j)
* @return Value of the Jacobian matrix at (i, j).
*
* The Jacobian must have been generated by generateJacobianMatrix() before calling this.
*/
[[nodiscard]] virtual double getJacobianMatrixEntry(
int i,
int j
const fourdst::atomic::Species& rowSpecies,
const fourdst::atomic::Species& colSpecies
) const = 0;
@@ -190,22 +192,22 @@ namespace gridfire {
/**
* @brief Get an entry from the stoichiometry matrix.
*
* @param speciesIndex Index of the species.
* @param reactionIndex Index of the reaction.
* @param species species to look up stoichiometry for.
* @param reaction reaction to find
* @return Stoichiometric coefficient for the species in the reaction.
*
* The stoichiometry matrix must have been generated by generateStoichiometryMatrix().
*/
[[nodiscard]] virtual int getStoichiometryMatrixEntry(
int speciesIndex,
int reactionIndex
const fourdst::atomic::Species& species,
const reaction::Reaction& reaction
) const = 0;
/**
* @brief Calculate the molar reaction flow for a given reaction.
*
* @param reaction The reaction for which to calculate the flow.
* @param Y Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Molar flow rate for the reaction (e.g., mol/g/s).
@@ -215,7 +217,7 @@ namespace gridfire {
*/
[[nodiscard]] virtual double calculateMolarReactionFlow(
const reaction::Reaction& reaction,
const std::vector<double>& Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const = 0;
@@ -223,7 +225,7 @@ namespace gridfire {
/**
* @brief Calculate the derivatives of the energy generation rate with respect to T and rho.
*
* @param Y Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return EnergyDerivatives containing dEps/dT and dEps/dRho.
@@ -232,9 +234,9 @@ namespace gridfire {
* generation rate with respect to temperature and density for the current state.
*/
[[nodiscard]] virtual EnergyDerivatives calculateEpsDerivatives(
const std::vector<double>& Y,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const = 0;
/**
@@ -249,7 +251,7 @@ namespace gridfire {
/**
* @brief Compute timescales for all species in the network.
*
* @param Y Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Map from Species to their characteristic timescales (s).
@@ -258,13 +260,13 @@ namespace gridfire {
* which can be used for timestep control, diagnostics, and reaction network culling.
*/
[[nodiscard]] virtual std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const std::vector<double>& Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const = 0;
[[nodiscard]] virtual std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const std::vector<double>& Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const = 0;

View File

@@ -24,6 +24,8 @@
#include "cppad/cppad.hpp"
#include "cppad/utility/sparse_rc.hpp"
#include "cppad/speed/sparse_jac_fun.hpp"
#include "gridfire/reaction/weak/weak_interpolator.h"
#include "gridfire/reaction/weak/weak_rate_library.h"
// PERF: The function getNetReactionStoichiometry returns a map of species to their stoichiometric coefficients for a given reaction.
// this makes extra copies of the species, which is not ideal and could be optimized further.
@@ -106,13 +108,13 @@ namespace gridfire {
*/
explicit GraphEngine(
const fourdst::composition::Composition &composition,
const BuildDepthType = NetworkBuildDepth::Full
BuildDepthType = NetworkBuildDepth::Full
);
explicit GraphEngine(
const fourdst::composition::Composition &composition,
const partition::PartitionFunction& partitionFunction,
const BuildDepthType buildDepth = NetworkBuildDepth::Full
BuildDepthType buildDepth = NetworkBuildDepth::Full
);
/**
@@ -128,7 +130,7 @@ namespace gridfire {
/**
* @brief Calculates the right-hand side (dY/dt) and energy generation rate.
*
* @param Y Vector of current abundances for all species.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return StepDerivatives<double> containing dY/dt and energy generation rate.
@@ -139,21 +141,21 @@ namespace gridfire {
* @see StepDerivatives
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const std::vector<double>& Y,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const std::vector<double>& Y,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
* @brief Generates the Jacobian matrix for the current state.
*
* @param Y_dynamic Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
*
@@ -164,13 +166,13 @@ namespace gridfire {
* @see getJacobianMatrixEntry()
*/
void generateJacobianMatrix(
const std::vector<double>& Y_dynamic,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
void generateJacobianMatrix(
const std::vector<double> &Y_dynamic,
const fourdst::composition::Composition& comp,
double T9,
double rho,
const SparsityPattern &sparsityPattern
@@ -188,7 +190,7 @@ namespace gridfire {
* @brief Calculates the molar reaction flow for a given reaction.
*
* @param reaction The reaction for which to calculate the flow.
* @param Y Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Molar flow rate for the reaction (e.g., mol/g/s).
@@ -198,9 +200,9 @@ namespace gridfire {
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction& reaction,
const std::vector<double>&Y,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
@@ -220,8 +222,8 @@ namespace gridfire {
/**
* @brief Gets an entry from the previously generated Jacobian matrix.
*
* @param i Row index (species index).
* @param j Column index (species index).
* @param rowSpecies Species corresponding to the row index (i).
* @param colSpecies Species corresponding to the column index (j).
* @return Value of the Jacobian matrix at (i, j).
*
* The Jacobian must have been generated by `generateJacobianMatrix()` before calling this.
@@ -229,8 +231,8 @@ namespace gridfire {
* @see generateJacobianMatrix()
*/
[[nodiscard]] double getJacobianMatrixEntry(
const int i,
const int j
const fourdst::atomic::Species& rowSpecies,
const fourdst::atomic::Species& colSpecies
) const override;
/**
@@ -246,8 +248,8 @@ namespace gridfire {
/**
* @brief Gets an entry from the stoichiometry matrix.
*
* @param speciesIndex Index of the species.
* @param reactionIndex Index of the reaction.
* @param species Species to look up stoichiometry for.
* @param reaction Reaction to find.
* @return Stoichiometric coefficient for the species in the reaction.
*
* The stoichiometry matrix must have been generated by `generateStoichiometryMatrix()`.
@@ -255,14 +257,14 @@ namespace gridfire {
* @see generateStoichiometryMatrix()
*/
[[nodiscard]] int getStoichiometryMatrixEntry(
const int speciesIndex,
const int reactionIndex
const fourdst::atomic::Species& species,
const reaction::Reaction& reaction
) const override;
/**
* @brief Computes timescales for all species in the network.
*
* @param Y Vector of current abundances.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Map from Species to their characteristic timescales (s).
@@ -271,13 +273,13 @@ namespace gridfire {
* which can be used for timestep control or diagnostics.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const std::vector<double>& Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const std::vector<double>& Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
@@ -396,7 +398,7 @@ namespace gridfire {
* @param reaction The reaction for which to calculate the reverse rate.
* @param T9 Temperature in units of 10^9 K.
* @param rho
* @param Y
* @param comp Composition object containing current abundances.
* @return Reverse rate for the reaction (e.g., mol/g/s).
*
* This method computes the reverse rate based on the forward rate and
@@ -404,7 +406,9 @@ namespace gridfire {
*/
[[nodiscard]] double calculateReverseRate(
const reaction::Reaction &reaction,
double T9, double rho, const std::vector<double> &Y
double T9,
double rho,
const fourdst::composition::Composition& comp
) const;
/**
@@ -428,8 +432,10 @@ namespace gridfire {
[[nodiscard]] double calculateReverseRateTwoBodyDerivative(
const reaction::Reaction &reaction,
const double T9,
double rho, const std::vector<double> &Y, const double reverseRate
double T9,
double rho,
const fourdst::composition::Composition& comp,
double reverseRate
) const;
/**
@@ -577,12 +583,16 @@ namespace gridfire {
constants m_constants;
rates::weak::WeakRateInterpolator m_weakRateInterpolator; ///< Interpolator for weak reaction rates.
reaction::ReactionSet m_reactions; ///< Set of REACLIB reactions in the network.
std::unordered_map<std::string_view, reaction::Reaction*> m_reactionIDMap; ///< Map from reaction ID to REACLIBReaction. //PERF: This makes copies of REACLIBReaction and could be a performance bottleneck.
std::vector<fourdst::atomic::Species> m_networkSpecies; ///< Vector of unique species in the network.
std::unordered_map<std::string_view, fourdst::atomic::Species> m_networkSpeciesMap; ///< Map from species name to Species object.
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.
boost::numeric::ublas::compressed_matrix<int> m_stoichiometryMatrix; ///< Stoichiometry matrix (species x reactions).
@@ -680,10 +690,11 @@ namespace gridfire {
[[nodiscard]] StepDerivatives<double> calculateAllDerivativesUsingPrecomputation(
const std::vector<double> &Y_in,
const fourdst::composition::Composition &comp,
const std::vector<double>& bare_rates,
const std::vector<double> &bare_reverse_rates,
double T9, double rho
double T9,
double rho
) const;
/**
@@ -691,9 +702,11 @@ namespace gridfire {
*
* @tparam T The numeric type to use for the calculation.
* @param reaction The reaction for which to calculate the flow.
* @param Y Vector of current abundances.
* @param Y Vector of molar abundances for all species in the network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @param Ye
* @param mue
* @return Molar flow rate for the reaction (e.g., mol/g/s).
*
* This method computes the net rate at which the given reaction proceeds
@@ -702,17 +715,17 @@ namespace gridfire {
template <IsArithmeticOrAD T>
T calculateMolarReactionFlow(
const reaction::Reaction &reaction,
const std::vector<T> &Y,
const std::vector<T>& Y,
const T T9,
const T rho
const T rho, T Ye, T mue
) const;
template<IsArithmeticOrAD T>
T calculateReverseMolarReactionFlow(
T T9,
T rho,
const T T9,
const T rho,
std::vector<T> screeningFactors,
std::vector<T> Y,
const std::vector<T>& Y,
size_t reactionIndex,
const reaction::Reaction &reaction
) const;
@@ -721,9 +734,11 @@ namespace gridfire {
* @brief Calculates all derivatives (dY/dt) and the energy generation rate.
*
* @tparam T The numeric type to use for the calculation.
* @param Y_in Vector of current abundances for all species.
* @param Y_in Vector of molar abundances for all species in the network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @param Ye
* @param mue
* @return StepDerivatives<T> containing dY/dt and energy generation rate.
*
* This method calculates the time derivatives of all species and the
@@ -731,46 +746,46 @@ namespace gridfire {
*/
template<IsArithmeticOrAD T>
[[nodiscard]] StepDerivatives<T> calculateAllDerivatives(
const std::vector<T> &Y_in,
const std::vector<T>& Y_in,
T T9,
T rho
T rho, T Ye, T mue
) const;
/**
* @brief Calculates all derivatives (dY/dt) and the energy generation rate (double precision).
*
* @param Y_in Vector of current abundances for all species.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return StepDerivatives<double> containing dY/dt and energy generation rate.
*
* This method calculates the time derivatives of all species and the
* specific nuclear energy generation rate for the current state using
* double precision arithmetic.
*/
[[nodiscard]] StepDerivatives<double> calculateAllDerivatives(
const std::vector<double>& Y_in,
const double T9,
const double rho
) const;
/**
* @brief Calculates all derivatives (dY/dt) and the energy generation rate (automatic differentiation).
*
* @param Y_in Vector of current abundances for all species.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return StepDerivatives<ADDouble> containing dY/dt and energy generation rate.
*
* This method calculates the time derivatives of all species and the
* specific nuclear energy generation rate for the current state using
* automatic differentiation.
*/
[[nodiscard]] StepDerivatives<ADDouble> calculateAllDerivatives(
const std::vector<ADDouble>& Y_in,
const ADDouble &T9,
const ADDouble &rho
) const;
// /**
// * @brief Calculates all derivatives (dY/dt) and the energy generation rate (double precision).
// *
// * @param Y Vector of molar abundances for all species in the network.
// * @param T9 Temperature in units of 10^9 K.
// * @param rho Density in g/cm^3.
// * @return StepDerivatives<double> containing dY/dt and energy generation rate.
// *
// * This method calculates the time derivatives of all species and the
// * specific nuclear energy generation rate for the current state using
// * double precision arithmetic.
// */
// [[nodiscard]] StepDerivatives<double> calculateAllDerivatives(
// const std::vector<double>& Y,
// double T9,
// double rho
// ) const;
//
// /**
// * @brief Calculates all derivatives (dY/dt) and the energy generation rate (automatic differentiation).
// *
// * @param Y Vector of molar abundances for all species in the network.
// * @param T9 Temperature in units of 10^9 K.
// * @param rho Density in g/cm^3.
// * @return StepDerivatives<ADDouble> containing dY/dt and energy generation rate.
// *
// * This method calculates the time derivatives of all species and the
// * specific nuclear energy generation rate for the current state using
// * automatic differentiation.
// */
// [[nodiscard]] StepDerivatives<ADDouble> calculateAllDerivatives(
// const std::vector<ADDouble> &Y,
// ADDouble T9,
// ADDouble rho
// ) const;
};
@@ -780,7 +795,7 @@ namespace gridfire {
T T9,
T rho,
std::vector<T> screeningFactors,
std::vector<T> Y,
const std::vector<T>& Y,
size_t reactionIndex,
const reaction::Reaction &reaction
) const {
@@ -804,9 +819,15 @@ namespace gridfire {
} else {
return reverseMolarFlow; // If no atomic function is available, return zero
}
} else {
} else { // The case where T is of type double
// A,B If not calling with an AD type, calculate the reverse rate directly
reverseRateConstant = calculateReverseRate(reaction, T9, 0, {});
std::vector<std::string> symbols;
symbols.reserve(m_networkSpecies.size());
for (const auto& species : m_networkSpecies) {
symbols.emplace_back(species.name());
}
fourdst::composition::Composition comp(symbols, Y);
reverseRateConstant = calculateReverseRate(reaction, T9, rho, comp);
}
// C. Get product multiplicities
@@ -824,7 +845,7 @@ namespace gridfire {
// E. Calculate the abundance term
T productAbundanceTerm = static_cast<T>(1.0);
for (const auto& [species, count] : productCounts) {
const unsigned long speciesIndex = m_speciesToIndexMap.at(species);
const size_t speciesIndex = m_speciesToIndexMap.at(species);
productAbundanceTerm *= CppAD::pow(Y[speciesIndex], count);
}
@@ -844,7 +865,12 @@ namespace gridfire {
template<IsArithmeticOrAD T>
StepDerivatives<T> GraphEngine::calculateAllDerivatives(
const std::vector<T> &Y_in, T T9, T rho) const {
const std::vector<T>& Y_in,
const T T9,
const T rho,
const T Ye,
const T mue
) const {
std::vector<T> screeningFactors = m_screeningModel->calculateScreeningFactors(
m_reactions,
m_networkSpecies,
@@ -854,8 +880,10 @@ namespace gridfire {
);
// --- Setup output derivatives structure ---
StepDerivatives<T> result;
result.dydt.resize(m_networkSpecies.size(), static_cast<T>(0.0));
StepDerivatives<T> result{};
for (const auto& species : m_networkSpecies) {
result.dydt[species] = static_cast<T>(0.0); // default the change in abundance to zero
}
// --- AD Pre-setup (flags to control conditionals in an AD safe / branch aware manner) ---
// ----- Constants for AD safe calculations ---
@@ -885,13 +913,16 @@ namespace gridfire {
const T N_A = static_cast<T>(m_constants.Na); // Avogadro's number in mol^-1
const T c = static_cast<T>(m_constants.c); // Speed of light in cm/s
// TODO: It may be prudent to introduce assertions here which validate units but will be removed in release builds (to ensure that unit inconsistencies do not creep in during future development)
// libconstants already has units built in so this should be straightforward.
// --- SINGLE LOOP OVER ALL REACTIONS ---
for (size_t reactionIndex = 0; reactionIndex < m_reactions.size(); ++reactionIndex) {
const auto& reaction = m_reactions[reactionIndex];
// 1. Calculate forward reaction rate
const T forwardMolarReactionFlow = screeningFactors[reactionIndex] *
calculateMolarReactionFlow<T>(reaction, Y, T9, rho);
calculateMolarReactionFlow<T>(reaction, Y, T9, rho, Ye, mue);
// 2. Calculate reverse reaction rate
T reverseMolarFlow = static_cast<T>(0.0);
@@ -910,15 +941,15 @@ namespace gridfire {
const T molarReactionFlow = forwardMolarReactionFlow - reverseMolarFlow; // Net molar reaction flow
// 3. Use the rate to update all relevant species derivatives (dY/dt)
for (size_t speciesIndex = 0; speciesIndex < m_networkSpecies.size(); ++speciesIndex) {
const T nu_ij = static_cast<T>(m_stoichiometryMatrix(speciesIndex, reactionIndex));
result.dydt[speciesIndex] += threshold_flag * nu_ij * molarReactionFlow;
for (const auto& species: m_networkSpecies) {
const T nu_ij = static_cast<T>(reaction.stoichiometry(species));
result.dydt[species] += threshold_flag * nu_ij * molarReactionFlow;
}
}
T massProductionRate = static_cast<T>(0.0); // [mol][s^-1]
for (const auto& [species, index] : m_speciesToIndexMap) {
massProductionRate += result.dydt[index] * species.mass() * u;
for (const auto &species: m_speciesToIndexMap | std::views::keys) {
massProductionRate += result.dydt.at(species) * species.mass() * u;
}
result.nuclearEnergyGenerationRate = -massProductionRate * N_A * c * c; // [cm^2][s^-3] = [erg][s^-1][g^-1]
@@ -930,9 +961,11 @@ namespace gridfire {
template <IsArithmeticOrAD T>
T GraphEngine::calculateMolarReactionFlow(
const reaction::Reaction &reaction,
const std::vector<T> &Y,
const std::vector<T>& Y,
const T T9,
const T rho
const T rho,
const T Ye,
const T mue
) const {
// --- Pre-setup (flags to control conditionals in an AD safe / branch aware manner) ---
@@ -940,7 +973,7 @@ namespace gridfire {
const T zero = static_cast<T>(0.0);
// --- Calculate the molar reaction rate (in units of [s^-1][cm^3(N-1)][mol^(1-N)] for N reactants) ---
const T k_reaction = reaction.calculate_rate(T9, rho, Y);
const T k_reaction = reaction.calculate_rate(T9, rho, Ye, mue, Y, m_indexToSpeciesMap);
// --- Cound the number of each reactant species to account for species multiplicity ---
std::unordered_map<std::string, int> reactant_counts;

View File

@@ -7,6 +7,8 @@
#include <variant>
#include "gridfire/reaction/weak/weak_interpolator.h"
namespace gridfire {
/**
@@ -21,6 +23,7 @@ namespace gridfire {
*
* @param composition Mapping of isotopic species to their mass fractions; species with positive
* mass fraction seed the network.
* @param weakInterpolator
* @param maxLayers Variant specifying either a predefined NetworkBuildDepth or a custom integer depth;
* negative depth (Full) collects all reactions, zero is invalid.
* @param reverse If true, collects reverse reactions (decays or back-reactions); if false, uses forward reactions.
@@ -32,7 +35,7 @@ namespace gridfire {
*/
reaction::ReactionSet build_reaclib_nuclear_network(
const fourdst::composition::Composition &composition,
BuildDepthType maxLayers = NetworkBuildDepth::Full,
bool reverse = false
const rates::weak::WeakRateInterpolator &weakInterpolator,
BuildDepthType maxLayers = NetworkBuildDepth::Full, bool reverse = false
);
}
}

View File

@@ -37,7 +37,7 @@ namespace gridfire {
*
* @param engine Engine providing the current set of network reactions and flow calculations.
* @param species The atomic species whose destruction rate is computed.
* @param Y Vector of molar abundances for all species in the engine.
* @param composition Current composition providing abundances for all species.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density of the medium.
* @pre Y.size() matches engine.getNetworkReactions().size() mapping species order.
@@ -47,7 +47,7 @@ namespace gridfire {
double calculateDestructionRateConstant(
const DynamicEngine& engine,
const fourdst::atomic::Species& species,
const std::vector<double>& Y,
const fourdst::composition::Composition& composition,
double T9,
double rho
);
@@ -60,7 +60,7 @@ namespace gridfire {
*
* @param engine Engine providing the current set of network reactions and flow calculations.
* @param species The atomic species whose creation rate is computed.
* @param Y Vector of molar abundances for all species in the engine.
* @param composition Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density of the medium.
* @pre Y.size() matches engine.getNetworkReactions().size() mapping species order.
@@ -70,7 +70,7 @@ namespace gridfire {
double calculateCreationRate(
const DynamicEngine& engine,
const fourdst::atomic::Species& species,
const std::vector<double>& Y,
const fourdst::composition::Composition& composition,
double T9,
double rho
);

View File

@@ -88,7 +88,7 @@ namespace gridfire {
/**
* @brief Calculates the right-hand side (dY/dt) and energy generation for the active species.
*
* @param Y_culled A vector of abundances for the active species.
* @param comp The current composition of the system.
* @param T9 The temperature in units of 10^9 K.
* @param rho The density in g/cm^3.
* @return A StepDerivatives struct containing the derivatives of the active species and the
@@ -102,21 +102,29 @@ namespace gridfire {
* @see AdaptiveEngineView::update()
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const std::vector<double> &Y_culled,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
*
* @param comp The current composition of the system.
* @param T9 The temperature in units of 10^9 K.
* @param rho The density in g/cm^3.
* @return A struct containing the derivatives of the energy generation rate with respect to temperature and density.
*/
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const std::vector<double> &Y_culled,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
* @brief Generates the Jacobian matrix for the active species.
*
* @param Y_dynamic A vector of abundances for the active species.
* @param comp The current composition of the system.
* @param T9 The temperature in units of 10^9 K.
* @param rho The density in g/cm^3.
*
@@ -127,16 +135,16 @@ namespace gridfire {
* @see AdaptiveEngineView::update()
*/
void generateJacobianMatrix(
const std::vector<double> &Y_dynamic,
const double T9,
const double rho
const fourdst::composition::Composition &comp,
double T9,
double rho
) const override;
/**
* @brief Gets an entry from the Jacobian matrix for the active species.
*
* @param i_culled The row index (species index) in the culled matrix.
* @param j_culled The column index (species index) in the culled matrix.
* @param rowSpecies The species corresponding to the row index in the culled species list.
* @param colSpecies The species corresponding to the column index in the culled species list
* @return The value of the Jacobian matrix at (i_culled, j_culled).
*
* This method maps the culled indices to the full network indices and calls the base engine
@@ -147,8 +155,8 @@ namespace gridfire {
* @see AdaptiveEngineView::update()
*/
[[nodiscard]] double getJacobianMatrixEntry(
const int i_culled,
const int j_culled
const fourdst::atomic::Species& rowSpecies,
const fourdst::atomic::Species& colSpecies
) const override;
/**
@@ -165,8 +173,8 @@ namespace gridfire {
/**
* @brief Gets an entry from the stoichiometry matrix for the active species and reactions.
*
* @param speciesIndex_culled The index of the species in the culled species list.
* @param reactionIndex_culled The index of the reaction in the culled reaction list.
* @param species The species for which to get the stoichiometric coefficient.
* @param reaction The reaction for which to get the stoichiometric coefficient.
* @return The stoichiometric coefficient for the given species and reaction.
*
* This method maps the culled indices to the full network indices and calls the base engine
@@ -177,15 +185,15 @@ namespace gridfire {
* @see AdaptiveEngineView::update()
*/
[[nodiscard]] int getStoichiometryMatrixEntry(
const int speciesIndex_culled,
const int reactionIndex_culled
const fourdst::atomic::Species& species,
const reaction::Reaction& reaction
) const override;
/**
* @brief Calculates the molar reaction flow for a given reaction in the active network.
*
* @param reaction The reaction for which to calculate the flow.
* @param Y_culled Vector of current abundances for the active species.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Molar flow rate for the reaction (e.g., mol/g/s).
@@ -198,7 +206,7 @@ namespace gridfire {
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction &reaction,
const std::vector<double> &Y_culled,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const override;
@@ -215,7 +223,7 @@ namespace gridfire {
/**
* @brief Computes timescales for all active species in the network.
*
* @param Y_culled Vector of current abundances for the active species.
* @param comp Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Map from Species to their characteristic timescales (s).
@@ -226,13 +234,13 @@ namespace gridfire {
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const std::vector<double> &Y_culled,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const override;
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const std::vector<double> &Y,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const override;
@@ -391,21 +399,18 @@ namespace gridfire {
* full network.
*
* @param netIn The current network input, containing temperature, density, and composition.
* @param out_Y_Full A vector that will be populated with the molar abundances of all species in the full network.
* @return A vector of ReactionFlow structs, each containing a pointer to a reaction and its calculated flow rate.
* @return A pair with the first element a vector of ReactionFlow structs, each containing a pointer to a reaction and its calculated flow rate and the second being a composition object where species which were not present in netIn but are present in the definition of the base engine are registered but have 0 mass fraction.
*
* @par Algorithm:
* 1. Clears and reserves space in `out_Y_Full`.
* 2. Iterates through all species in the base engine's network.
* 3. For each species, it retrieves the molar abundance from `netIn.composition`. If the species is not found, its abundance is set to 0.0.
* 4. Converts the temperature from Kelvin to T9.
* 5. Iterates through all reactions in the base engine's network.
* 6. For each reaction, it calls the base engine's `calculateMolarReactionFlow` to get the flow rate.
* 7. Stores the reaction pointer and its flow rate in a `ReactionFlow` struct and adds it to the returned vector.
* 1. Iterates through all species in the base engine's network.
* 2. For each species, it retrieves the molar abundance from `netIn.composition`. If the species is not found, its abundance is set to 0.0.
* 3. Converts the temperature from Kelvin to T9.
* 4. Iterates through all reactions in the base engine's network.
* 5. For each reaction, it calls the base engine's `calculateMolarReactionFlow` to get the flow rate.
* 6. Stores the reaction pointer and its flow rate in a `ReactionFlow` struct and adds it to the returned vector.
*/
std::vector<ReactionFlow> calculateAllReactionFlows(
const NetIn& netIn,
std::vector<double>& out_Y_Full
std::pair<std::vector<ReactionFlow>, fourdst::composition::Composition> calculateAllReactionFlows(
const NetIn& netIn
) const;
/**
* @brief Finds all species that are reachable from the initial fuel through the reaction network.
@@ -436,7 +441,7 @@ namespace gridfire {
*
* @param allFlows A vector of all reactions and their flow rates.
* @param reachableSpecies A set of all species reachable from the initial fuel.
* @param Y_full A vector of molar abundances for all species in the full network.
* @param comp The current composition of the system.
* @param maxFlow The maximum reaction flow rate in the network.
* @return A vector of pointers to the reactions that have been kept after culling.
*
@@ -450,15 +455,15 @@ namespace gridfire {
[[nodiscard]] std::vector<const reaction::Reaction*> cullReactionsByFlow(
const std::vector<ReactionFlow>& allFlows,
const std::unordered_set<fourdst::atomic::Species>& reachableSpecies,
const std::vector<double>& Y_full,
const fourdst::composition::Composition& comp,
double maxFlow
) const;
typedef std::pair<std::unordered_set<const reaction::Reaction*>, std::unordered_set<fourdst::atomic::Species>> RescueSet;
[[nodiscard]] RescueSet rescueEdgeSpeciesDestructionChannel(
const std::vector<double>& Y_full,
const double T9,
const double rho,
const fourdst::composition::Composition& comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species>& activeSpecies,
const reaction::ReactionSet& activeReactions
) const;

View File

@@ -29,7 +29,7 @@ namespace gridfire{
/**
* @brief Calculates the right-hand side (dY/dt) and energy generation for the active species.
*
* @param Y_defined A vector of abundances for the active species.
* @param comp A Composition object containing the current composition of the system
* @param T9 The temperature in units of 10^9 K.
* @param rho The density in g/cm^3.
* @return A StepDerivatives struct containing the derivatives of the active species and the
@@ -38,44 +38,44 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale (i.e., `update()` has not been called after `setNetworkFile()`).
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const std::vector<double>& Y_defined,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const std::vector<double> &Y,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
* @brief Generates the Jacobian matrix for the active species.
*
* @param Y_dynamic A vector of abundances for the active species.
* @param comp A Composition object containing the current composition of the system
* @param T9 The temperature in units of 10^9 K.
* @param rho The density in g/cm^3.
*
* @throws std::runtime_error If the view is stale.
*/
void generateJacobianMatrix(
const std::vector<double>& Y_dynamic,
const fourdst::composition::Composition& comp,
const double T9,
const double rho
) const override;
/**
* @brief Gets an entry from the Jacobian matrix for the active species.
*
* @param i_defined The row index (species index) in the defined matrix.
* @param j_defined The column index (species index) in the defined matrix.
* @return The value of the Jacobian matrix at (i_defined, j_defined).
* @param rowSpecies The species corresponding to the row index.
* @param colSpecies The species corresponding to the column index.
* @return The value of the Jacobian matrix at (row species index, col species index).
*
* @throws std::runtime_error If the view is stale.
* @throws std::out_of_range If an index is out of bounds.
*/
[[nodiscard]] double getJacobianMatrixEntry(
const int i_defined,
const int j_defined
const fourdst::atomic::Species& rowSpecies,
const fourdst::atomic::Species& colSpecies
) const override;
/**
* @brief Generates the stoichiometry matrix for the active reactions and species.
@@ -86,22 +86,22 @@ namespace gridfire{
/**
* @brief Gets an entry from the stoichiometry matrix for the active species and reactions.
*
* @param speciesIndex_defined The index of the species in the defined species list.
* @param reactionIndex_defined The index of the reaction in the defined reaction list.
* @param species The species for which to get the stoichiometric coefficient.
* @param reaction The reaction for which to get the stoichiometric coefficient.
* @return The stoichiometric coefficient for the given species and reaction.
*
* @throws std::runtime_error If the view is stale.
* @throws std::out_of_range If an index is out of bounds.
*/
[[nodiscard]] int getStoichiometryMatrixEntry(
const int speciesIndex_defined,
const int reactionIndex_defined
const fourdst::atomic::Species& species,
const reaction::Reaction& reaction
) const override;
/**
* @brief Calculates the molar reaction flow for a given reaction in the active network.
*
* @param reaction The reaction for which to calculate the flow.
* @param Y_defined Vector of current abundances for the active species.
* @param comp A Composition object containing the current composition of the system
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Molar flow rate for the reaction (e.g., mol/g/s).
@@ -110,9 +110,9 @@ namespace gridfire{
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction& reaction,
const std::vector<double>& Y_defined,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
* @brief Gets the set of active logical reactions in the network.
@@ -127,7 +127,7 @@ namespace gridfire{
/**
* @brief Computes timescales for all active species in the network.
*
* @param Y_defined Vector of current abundances for the active species.
* @param comp A Composition object containing the current composition of the system
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Map from Species to their characteristic timescales (s).
@@ -135,15 +135,15 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const std::vector<double>& Y_defined,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const std::vector<double>& Y_defined,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**

View File

@@ -206,7 +206,7 @@ namespace gridfire {
/**
* @brief Calculates the right-hand side (dY/dt) and energy generation.
*
* @param Y_full Vector of current molar abundances for all species in the base engine.
* @param comp The current composition.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A `std::expected` containing `StepDerivatives<double>` on success, or a
@@ -231,21 +231,21 @@ namespace gridfire {
* (T9, rho, Y_full). This indicates `update()` was not called recently enough.
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const std::vector<double> &Y_full,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const std::vector<double> &Y,
const double T9,
const double rho
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
/**
* @brief Generates the Jacobian matrix for the current state.
*
* @param Y_full Vector of current molar abundances.
* @param comp The current composition.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
*
@@ -266,7 +266,7 @@ namespace gridfire {
* without a valid partition.
*/
void generateJacobianMatrix(
const std::vector<double> &Y_full,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
@@ -274,8 +274,8 @@ namespace gridfire {
/**
* @brief Gets an entry from the previously generated Jacobian matrix.
*
* @param i_full Row index (species index) in the full network.
* @param j_full Column index (species index) in the full network.
* @param rowSpecies Species corresponding to the row index (i_full).
* @param colSpecies Species corresponding to the column index (j_full).
* @return Value of the Jacobian matrix at (i_full, j_full).
*
* @par Purpose
@@ -289,8 +289,8 @@ namespace gridfire {
* @pre `generateJacobianMatrix()` must have been called for the current state.
*/
[[nodiscard]] double getJacobianMatrixEntry(
int i_full,
int j_full
const fourdst::atomic::Species& rowSpecies,
const fourdst::atomic::Species& colSpecies
) const override;
/**
@@ -308,8 +308,8 @@ namespace gridfire {
/**
* @brief Gets an entry from the stoichiometry matrix.
*
* @param speciesIndex Index of the species in the full network.
* @param reactionIndex Index of the reaction in the full network.
* @param species Species to look up stoichiometry for.
* @param reaction Reaction to find.
* @return Stoichiometric coefficient for the species in the reaction.
*
* @par Purpose
@@ -321,15 +321,15 @@ namespace gridfire {
* @pre `generateStoichiometryMatrix()` must have been called.
*/
[[nodiscard]] int getStoichiometryMatrixEntry(
int speciesIndex,
int reactionIndex
const fourdst::atomic::Species& species,
const reaction::Reaction& reaction
) const override;
/**
* @brief Calculates the molar reaction flow for a given reaction.
*
* @param reaction The reaction for which to calculate the flow.
* @param Y_full Vector of current molar abundances for the full network.
* @param comp The current composition.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return Molar flow rate for the reaction (e.g., mol/g/s).
@@ -349,7 +349,7 @@ namespace gridfire {
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction &reaction,
const std::vector<double> &Y_full,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
@@ -385,7 +385,7 @@ namespace gridfire {
/**
* @brief Computes timescales for all species in the network.
*
* @param Y Vector of current molar abundances for the full network.
* @param comp The current composition.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A `std::expected` containing a map from `Species` to their characteristic
@@ -403,7 +403,7 @@ namespace gridfire {
* @throws StaleEngineError If the QSE cache misses.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const std::vector<double> &Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
@@ -411,7 +411,7 @@ namespace gridfire {
/**
* @brief Computes destruction timescales for all species in the network.
*
* @param Y Vector of current molar abundances for the full network.
* @param comp The current composition.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A `std::expected` containing a map from `Species` to their characteristic
@@ -429,7 +429,7 @@ namespace gridfire {
* @throws StaleEngineError If the QSE cache misses.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const std::vector<double> &Y,
const fourdst::composition::Composition& comp,
double T9,
double rho
) const override;
@@ -516,7 +516,7 @@ namespace gridfire {
*
* @param timescale_pools A vector of vectors of species indices, where each inner vector
* represents a timescale pool.
* @param Y Vector of current molar abundances for the full network.
* @param comp Vector of current molar abundances for the full network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A vector of vectors of species indices, where each inner vector represents a
@@ -531,9 +531,9 @@ namespace gridfire {
* It then finds the connected components within that graph using a Breadth-First Search (BFS).
* The resulting components from all pools are collected and returned.
*/
std::vector<std::vector<size_t>> analyzeTimescalePoolConnectivity(
const std::vector<std::vector<size_t>> &timescale_pools,
const std::vector<double> &Y,
std::vector<std::vector<fourdst::atomic::Species>> analyzeTimescalePoolConnectivity(
const std::vector<std::vector<fourdst::atomic::Species>> &timescale_pools,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const;
@@ -541,7 +541,7 @@ namespace gridfire {
/**
* @brief Partitions the network into dynamic and algebraic (QSE) groups based on timescales.
*
* @param Y Vector of current molar abundances for the full network.
* @param comp Vector of current molar abundances for the full network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
*
@@ -567,7 +567,7 @@ namespace gridfire {
* partitioning.
*/
void partitionNetwork(
const std::vector<double>& Y,
const fourdst::composition::Composition &comp,
double T9,
double rho
);
@@ -605,9 +605,9 @@ namespace gridfire {
*/
void exportToDot(
const std::string& filename,
const std::vector<double>& Y,
const double T9,
const double rho
const fourdst::composition::Composition &Y,
double T9,
double rho
) const;
/**
@@ -679,7 +679,7 @@ namespace gridfire {
/**
* @brief Equilibrates the network by partitioning and solving for QSE abundances.
*
* @param Y Vector of current molar abundances for the full network.
* @param comp Vector of current molar abundances for the full network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A new composition object with the equilibrated abundances.
@@ -698,7 +698,7 @@ namespace gridfire {
* @post The engine's internal partition is updated. A new composition object is returned.
*/
fourdst::composition::Composition equilibrateNetwork(
const std::vector<double> &Y,
const fourdst::composition::Composition &comp,
double T9,
double rho
);
@@ -730,11 +730,10 @@ namespace gridfire {
* in quasi-steady-state equilibrium with each other.
*/
struct QSEGroup {
std::set<size_t> species_indices; ///< Indices of all species in this group.
bool is_in_equilibrium = false; ///< Flag set by flux analysis.
std::set<size_t> algebraic_indices; ///< Indices of algebraic species in this group.
std::set<size_t> seed_indices; ///< Indices of dynamic species in this group.
double mean_timescale; ///< Mean timescale of the group.
bool is_in_equilibrium = false; ///< Flag set by flux analysis.
std::set<fourdst::atomic::Species> algebraic_species; ///< Algebraic species in this group.
std::set<fourdst::atomic::Species> seed_species; ///< Dynamic species in this group.
double mean_timescale; ///< Mean timescale of the group.
/**
* @brief Less-than operator for QSEGroup, used for sorting.
@@ -761,9 +760,7 @@ namespace gridfire {
*/
bool operator!=(const QSEGroup& other) const;
std::string toString() const;
std::string toString(const DynamicEngine &engine) const;
[[nodiscard]] [[maybe_unused]] std::string toString() const;
};
/**
@@ -802,11 +799,11 @@ namespace gridfire {
/**
* @brief Indices of the species to solve for in the QSE group.
*/
const std::vector<size_t>& m_qse_solve_indices;
const std::set<fourdst::atomic::Species>& m_qse_solve_species;
/**
* @brief Initial abundances of all species in the full network.
*/
const std::vector<double>& m_Y_full_initial;
const fourdst::composition::Composition& m_initial_comp;
/**
* @brief Temperature in units of 10^9 K.
*/
@@ -820,41 +817,49 @@ namespace gridfire {
*/
const Eigen::VectorXd& m_Y_scale;
/**
* @brief Mapping from species to their indices in the QSE solve vector.
*/
const std::unordered_map<fourdst::atomic::Species, size_t> m_qse_solve_species_index_map;
/**
* @brief Constructs an EigenFunctor.
*
* @param view The MultiscalePartitioningEngineView instance.
* @param qse_solve_indices Indices of the species to solve for in the QSE group.
* @param Y_full_initial Initial abundances of all species.
* @param qse_solve_species Species to solve for in the QSE group.
* @param initial_comp Initial abundances of all species in the full network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @param Y_scale Scaling factors for the species abundances.
* @param qse_solve_species_index_map Mapping from species to their indices in the QSE solve vector.
*/
EigenFunctor(
MultiscalePartitioningEngineView& view,
const std::vector<size_t>& qse_solve_indices,
const std::vector<double>& Y_full_initial,
const std::set<fourdst::atomic::Species>& qse_solve_species,
const fourdst::composition::Composition& initial_comp,
const double T9,
const double rho,
const Eigen::VectorXd& Y_scale
const Eigen::VectorXd& Y_scale,
const std::unordered_map<fourdst::atomic::Species, size_t>& qse_solve_species_index_map
) :
m_view(&view),
m_qse_solve_indices(qse_solve_indices),
m_Y_full_initial(Y_full_initial),
m_qse_solve_species(qse_solve_species),
m_initial_comp(initial_comp),
m_T9(T9),
m_rho(rho),
m_Y_scale(Y_scale) {}
m_Y_scale(Y_scale),
m_qse_solve_species_index_map(qse_solve_species_index_map){}
/**
* @brief Gets the number of output values from the functor (size of the residual vector).
* @return The number of algebraic species being solved.
*/
[[nodiscard]] size_t values() const { return m_qse_solve_indices.size(); }
[[nodiscard]] size_t values() const { return m_qse_solve_species.size(); }
/**
* @brief Gets the number of input values to the functor (size of the variable vector).
* @return The number of algebraic species being solved.
*/
[[nodiscard]] size_t inputs() const { return m_qse_solve_indices.size(); }
[[nodiscard]] size_t inputs() const { return m_qse_solve_species.size(); }
/**
* @brief Evaluates the functor's residual vector `f_qse = dY_alg/dt`.
@@ -981,23 +986,15 @@ namespace gridfire {
* @brief The simplified set of species presented to the solver (the "slow" species).
*/
std::vector<fourdst::atomic::Species> m_dynamic_species;
/**
* @brief Indices mapping the dynamic species back to the base engine's full species list.
*/
std::vector<size_t> m_dynamic_species_indices;
/**
* @brief Species that are treated as algebraic (in QSE) in the QSE groups.
*/
std::vector<fourdst::atomic::Species> m_algebraic_species;
/**
* @breif Stateful storage of the current algebraic species abundances. This is updated every time the update method is called.
* @brief Map from species to their calculated abundances in the QSE state.
*/
std::vector<double> m_Y_algebraic;
/**
* @brief Indices of algebraic species in the full network.
*/
std::vector<size_t> m_algebraic_species_indices;
std::unordered_map<fourdst::atomic::Species, double> m_algebraic_abundances;
/**
* @brief Indices of all species considered active in the current partition (dynamic + algebraic).
@@ -1029,7 +1026,7 @@ namespace gridfire {
/**
* @brief Partitions the network by timescale.
*
* @param Y_full Vector of current molar abundances for all species.
* @param comp Vector of current molar abundances for all species.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A vector of vectors of species indices, where each inner vector represents a
@@ -1044,8 +1041,8 @@ namespace gridfire {
* a gap between consecutive timescales that is larger than a predefined threshold
* (e.g., a factor of 100).
*/
std::vector<std::vector<size_t>> partitionByTimescale(
const std::vector<double> &Y_full,
std::vector<std::vector<fourdst::atomic::Species>> partitionByTimescale(
const fourdst::composition::Composition &comp,
double T9,
double rho
) const;
@@ -1054,7 +1051,7 @@ namespace gridfire {
* @brief Validates candidate QSE groups using flux analysis.
*
* @param candidate_groups A vector of candidate QSE groups.
* @param Y Vector of current molar abundances for the full network.
* @param comp Vector of current molar abundances for the full network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A vector of validated QSE groups that meet the flux criteria.
@@ -1074,7 +1071,7 @@ namespace gridfire {
::
QSEGroup>> validateGroupsWithFluxAnalysis(
const std::vector<QSEGroup> &candidate_groups,
const std::vector<double> &Y,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const;
@@ -1082,7 +1079,7 @@ namespace gridfire {
/**
* @brief Solves for the QSE abundances of the algebraic species in a given state.
*
* @param Y_full Vector of current molar abundances for all species in the base engine.
* @param comp Vector of current molar abundances for all species in the base engine.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A vector of molar abundances for the algebraic species.
@@ -1099,8 +1096,8 @@ namespace gridfire {
* @pre The input state (Y_full, T9, rho) must be a valid physical state.
* @post The algebraic species in the QSE cache are updated with the new equilibrium abundances.
*/
std::vector<double> solveQSEAbundances(
const std::vector<double> &Y_full,
fourdst::composition::Composition solveQSEAbundances(
const fourdst::composition::Composition &comp,
double T9,
double rho
);
@@ -1110,7 +1107,7 @@ namespace gridfire {
*
* @param pools A vector of vectors of species indices, where each inner vector represents a
* timescale pool.
* @param Y Vector of current molar abundances for the full network.
* @param comp Vector of current molar abundances for the full network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return The index of the pool with the largest (slowest) mean destruction timescale.
@@ -1123,8 +1120,8 @@ namespace gridfire {
* pool and returns the index of the pool with the maximum mean timescale.
*/
size_t identifyMeanSlowestPool(
const std::vector<std::vector<size_t>>& pools,
const std::vector<double> &Y,
const std::vector<std::vector<fourdst::atomic::Species>>& pools,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const;
@@ -1144,8 +1141,8 @@ namespace gridfire {
* and one as a product), it adds edges between all reactants and products from
* that reaction that are also in the pool.
*/
std::unordered_map<size_t, std::vector<size_t>> buildConnectivityGraph(
const std::vector<size_t>& species_pool
std::unordered_map<fourdst::atomic::Species, std::vector<fourdst::atomic::Species>> buildConnectivityGraph(
const std::vector<fourdst::atomic::Species>& species_pool
) const;
/**
@@ -1153,7 +1150,7 @@ namespace gridfire {
*
* @param candidate_pools A vector of vectors of species indices, where each inner vector
* represents a connected pool of species with similar fast timescales.
* @param Y Vector of current molar abundances.
* @param comp Vector of current molar abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @return A vector of `QSEGroup` structs, ready for flux validation.
@@ -1168,8 +1165,8 @@ namespace gridfire {
* @post A list of candidate `QSEGroup` objects is returned.
*/
std::vector<QSEGroup> constructCandidateGroups(
const std::vector<std::vector<size_t>>& candidate_pools,
const std::vector<double>& Y,
const std::vector<std::vector<fourdst::atomic::Species>>& candidate_pools,
const fourdst::composition::Composition &comp,
double T9,
double rho
) const;

View File

@@ -2,7 +2,7 @@
#include <exception>
#include <string>
#include <iostream>
#include <vector>
namespace gridfire::exceptions {
class EngineError : public std::exception {};

View File

@@ -2,6 +2,7 @@
#include <string>
#include <iostream>
#include <utility>
namespace gridfire::expectations {
enum class EngineErrorTypes {
@@ -19,8 +20,8 @@ namespace gridfire::expectations {
std::string m_message;
const EngineErrorTypes type = EngineErrorTypes::FAILURE;
explicit EngineError(const std::string &message, const EngineErrorTypes type)
: m_message(message), type(type) {}
explicit EngineError(std::string message, const EngineErrorTypes type)
: m_message(std::move(message)), type(type) {}
virtual ~EngineError() = default;

View File

@@ -99,7 +99,7 @@ namespace gridfire::io {
* ParsedNetworkData data = parser.parse("reactions.txt");
* @endcode
*/
ParsedNetworkData parse(const std::string& filename) const override;
[[nodiscard]] ParsedNetworkData parse(const std::string& filename) const override;
private:
using Config = fourdst::config::Config;
using LogManager = fourdst::logging::LogManager;
@@ -139,7 +139,7 @@ namespace gridfire::io {
* @throws std::runtime_error If the file cannot be opened or if it
* contains formatting errors.
*/
ParsedNetworkData parse(const std::string& filename) const override;
[[nodiscard]] ParsedNetworkData parse(const std::string& filename) const override;
private:
using Config = fourdst::config::Config;
using LogManager = fourdst::logging::LogManager;

View File

@@ -89,7 +89,7 @@ namespace gridfire {
*/
virtual NetOut evaluate(const NetIn &netIn) = 0;
virtual bool isStiff() const { return m_stiff; }
[[nodiscard]] virtual bool isStiff() const { return m_stiff; }
virtual void setStiff(const bool stiff) { m_stiff = stiff; }
protected:

View File

@@ -99,6 +99,6 @@ namespace gridfire::partition {
* @return Unique pointer to a new PartitionFunction instance of the given type.
* @throws std::runtime_error If the given type is not recognized.
+ */
std::unique_ptr<PartitionFunction> selectPartitionFunction(const BasePartitionType type) const;
[[nodiscard]] std::unique_ptr<PartitionFunction> selectPartitionFunction(const BasePartitionType type) const;
};
}

View File

@@ -11,6 +11,7 @@
#include "cppad/cppad.hpp"
#include "fourdst/composition/composition.h"
/**
* @file reaction.h
@@ -78,8 +79,18 @@ namespace gridfire::reaction {
public:
virtual ~Reaction() = default;
[[nodiscard]] virtual double calculate_rate(double T9, double rho, const std::vector<double>& Y) const = 0;
[[nodiscard]] virtual CppAD::AD<double> calculate_rate(CppAD::AD<double> T9, CppAD::AD<double> rho, const std::vector<CppAD::AD<double>>& Y) const = 0;
[[nodiscard]] virtual double calculate_rate(
double T9,
double rho,
double Ye,
double mue, const std::vector<double> &Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const = 0;
[[nodiscard]] virtual CppAD::AD<double> calculate_rate(
CppAD::AD<double> T9,
CppAD::AD<double> rho,
CppAD::AD<double> Ye,
CppAD::AD<double> mue, const std::vector<CppAD::AD<double>>& Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const = 0;
[[nodiscard]] virtual std::string_view id() const = 0;
[[nodiscard]] virtual const std::vector<fourdst::atomic::Species>& reactants() const = 0;
@@ -103,7 +114,26 @@ namespace gridfire::reaction {
[[nodiscard]] virtual uint64_t hash(uint64_t seed) const = 0;
[[nodiscard]] virtual double qValue() const = 0;
[[nodiscard]] virtual double calculate_forward_rate_log_derivative(double T9, double rho, const std::vector<double>& Y) const = 0;
[[nodiscard]] virtual double calculate_energy_generation_rate(
double T9,
double rho,
double Ye,
double mue, const std::vector<double>& Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const {
return calculate_rate(T9, rho, 0, 0, Y, index_to_species_map) * qValue();
}
[[nodiscard]] virtual CppAD::AD<double> calculate_energy_generation_rate(
const CppAD::AD<double>& T9,
const CppAD::AD<double>& rho,
const CppAD::AD<double> &Ye,
const CppAD::AD<double> &mue, const std::vector<CppAD::AD<double>>& Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const {
return calculate_rate(T9, rho, {}, {}, Y, index_to_species_map) * qValue();
}
[[nodiscard]] virtual double calculate_forward_rate_log_derivative(double T9, double rho, double Ye, double mue, const fourdst::composition::Composition& comp) const = 0;
[[nodiscard]] virtual ReactionType type() const = 0;
@@ -145,21 +175,37 @@ namespace gridfire::reaction {
* @brief Calculates the reaction rate for a given temperature.
* @param T9 The temperature in units of 10^9 K.
* @param rho Density [Not used in this implementation].
* @param Y Molar abundances of species [Not used in this implementation].
* @param Ye
* @param mue
* @param Y
* @param index_to_species_map
* @return The calculated reaction rate.
*/
[[nodiscard]] double calculate_rate(double T9, double rho, const std::vector<double>& Y) const override;
[[nodiscard]] double calculate_rate(
double T9,
double rho,
double Ye,
double mue, const std::vector<double> &Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const override;
/**
* @brief Calculates the reaction rate for a given temperature using CppAD types.
* @param T9 The temperature in units of 10^9 K, as a CppAD::AD<double>.
* @param rho Density, as a CppAD::AD<double> [Not used in this implementation].
* @param Ye
* @param mue
* @param Y Molar abundances of species, as a vector of CppAD::AD<double> [Not used in this implementation].
* @param index_to_species_map
* @return The calculated reaction rate, as a CppAD::AD<double>.
*/
[[nodiscard]] CppAD::AD<double> calculate_rate(CppAD::AD<double> T9, CppAD::AD<double> rho, const std::vector<CppAD::AD<double>>& Y) const override;
[[nodiscard]] CppAD::AD<double> calculate_rate(
CppAD::AD<double> T9,
CppAD::AD<double> rho,
CppAD::AD<double> Ye,
CppAD::AD<double> mue, const std::vector<CppAD::AD<double>>& Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const override;
[[nodiscard]] double calculate_forward_rate_log_derivative(double T9, double rho, const std::vector<double>& Y) const override;
[[nodiscard]] double calculate_forward_rate_log_derivative(double T9, double rho, double Ye, double mue, const fourdst::composition::Composition& comp) const override;
/**
* @brief Gets the reaction name in (projectile, ejectile) notation.
@@ -389,12 +435,24 @@ namespace gridfire::reaction {
* @brief Calculates the total reaction rate by summing all source rates.
* @param T9 The temperature in units of 10^9 K.
* @param rho
* @param Ye
* @param mue
* @param Y
* @param index_to_species_map
* @return The total calculated reaction rate.
*/
[[nodiscard]] double calculate_rate(double T9, double rho, const std::vector<double>& Y) const override;
[[nodiscard]] double calculate_rate(
double T9,
double rho,
double Ye,
double mue, const std::vector<double> &Y, const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const override;
[[nodiscard]] double calculate_forward_rate_log_derivative(double T9, double rho, const std::vector<double>& Y) const override;
[[nodiscard]] double calculate_forward_rate_log_derivative(
double T9,
double rho,
double Ye, double mue, const fourdst::composition::Composition& comp
) const override;
[[nodiscard]] ReactionType type() const override { return ReactionType::LOGICAL_REACLIB; }
@@ -404,10 +462,18 @@ namespace gridfire::reaction {
* @brief Calculates the total reaction rate using CppAD types.
* @param T9 The temperature in units of 10^9 K, as a CppAD::AD<double>.
* @param rho
* @param Ye
* @param mue
* @param Y
* @param index_to_species_map
* @return The total calculated reaction rate, as a CppAD::AD<double>.
*/
[[nodiscard]] CppAD::AD<double> calculate_rate(CppAD::AD<double> T9, CppAD::AD<double> rho, const std::vector<CppAD::AD<double>>& Y) const override;
[[nodiscard]] CppAD::AD<double> calculate_rate(
CppAD::AD<double> T9,
CppAD::AD<double> rho,
CppAD::AD<double> Ye,
CppAD::AD<double> mue, const std::vector<CppAD::AD<double>>& Y, const std::unordered_map<size_t,fourdst::atomic::Species>& index_to_species_map
) const override;
/** @name Iterators
* Provides iterators to loop over the rate coefficient sets.

View File

@@ -1,57 +1,254 @@
#pragma once
#include "fourdst/composition/atomicSpecies.h"
#define GRIDFIRE_WEAK_REACTION_LIB_SENTINEL -60.0
#include "gridfire/reaction/reaction.h"
#include "gridfire/reaction/weak/weak_types.h"
#include "gridfire/reaction/weak/weak_interpolator.h"
#include "gridfire/engine/engine_abstract.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/constants/const.h"
#include "cppad/cppad.hpp"
#include <memory>
#include <unordered_map>
#include <expected>
#include <vector>
#include <string>
#include <string_view>
#include <unordered_set>
namespace gridfire::rates::weak {
enum class WeakReactionType {
BETA_PLUS_DECAY,
BETA_MINUS_DECAY,
ELECTRON_CAPTURE,
POSITRON_CAPTURE,
};
inline std::unordered_map<WeakReactionType, std::string> WeakReactionTypeNames = {
{WeakReactionType::BETA_PLUS_DECAY, "β+ Decay"},
{WeakReactionType::BETA_MINUS_DECAY, "β- Decay"},
{WeakReactionType::ELECTRON_CAPTURE, "e- Capture"},
{WeakReactionType::POSITRON_CAPTURE, "e+ Capture"},
};
struct WeakReaction {
WeakReactionType type;
float T9;
float log_rhoYe;
float mu_e;
float log_rate;
float log_neutrino_loss;
friend std::ostream& operator<<(std::ostream& os, const WeakReaction& reaction) {
os << "WeakReaction(type=" << WeakReactionTypeNames[reaction.type]
<< ", T9=" << reaction.T9
<< ", log_rhoYe=" << reaction.log_rhoYe
<< ", mu_e=" << reaction.mu_e
<< ", log_rate=" << reaction.log_rate
<< ", log_neutrino_loss=" << reaction.log_neutrino_loss
<< ")";
return os;
}
};
class WeakReactionMap {
public:
WeakReactionMap();
~WeakReactionMap() = default;
std::vector<WeakReaction> get_all_reactions() const;
[[nodiscard]] std::vector<WeakReactionEntry> get_all_reactions() const;
std::expected<std::vector<WeakReaction>, bool> get_species_reactions(const fourdst::atomic::Species &species) const;
std::expected<std::vector<WeakReaction>, bool> get_species_reactions(const std::string& species_name) const;
[[nodiscard]] std::expected<std::vector<WeakReactionEntry>, WeakMapError> get_species_reactions(
const fourdst::atomic::Species &species) const;
[[nodiscard]] std::expected<std::vector<WeakReactionEntry>, WeakMapError> get_species_reactions(
const std::string &species_name) const;
private:
std::unordered_map<fourdst::atomic::Species, std::vector<WeakReaction>> m_weak_network;
std::unordered_map<fourdst::atomic::Species, std::vector<WeakReactionEntry>> m_weak_network;
};
class WeakReaction final : public reaction::Reaction {
public:
explicit WeakReaction(
const fourdst::atomic::Species &species,
WeakReactionType type,
const WeakRateInterpolator& interpolator
);
[[nodiscard]] double calculate_rate(
double T9,
double rho,
double Ye,
double mue,
const std::vector<double> &Y,
const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const override;
[[nodiscard]] CppAD::AD<double> calculate_rate(
CppAD::AD<double> T9,
CppAD::AD<double> rho,
CppAD::AD<double> Ye,
CppAD::AD<double> mue,
const std::vector<CppAD::AD<double>> &Y,
const std::unordered_map<size_t,fourdst::atomic::Species>& index_to_species_map
) const override;
[[nodiscard]] std::string_view id() const override { return m_id; }
[[nodiscard]] const std::vector<fourdst::atomic::Species> &reactants() const override { return {m_reactant}; }
[[nodiscard]] const std::vector<fourdst::atomic::Species> &products() const override { return {m_product}; }
[[nodiscard]] bool contains(const fourdst::atomic::Species &species) const override;
[[nodiscard]] bool contains_reactant(const fourdst::atomic::Species &species) const override;
[[nodiscard]] bool contains_product(const fourdst::atomic::Species &species) const override;
[[nodiscard]] std::unordered_set<fourdst::atomic::Species> all_species() const override;
[[nodiscard]] std::unordered_set<fourdst::atomic::Species> reactant_species() const override;
[[nodiscard]] std::unordered_set<fourdst::atomic::Species> product_species() const override;
[[nodiscard]] size_t num_species() const override { return 2; } // Always 2 for weak reactions
[[nodiscard]] std::unordered_map<fourdst::atomic::Species, int> stoichiometry() const override;
[[nodiscard]] int stoichiometry(const fourdst::atomic::Species &species) const override;
[[nodiscard]] uint64_t hash(uint64_t seed) const override;
[[nodiscard]] double qValue() const override;
[[nodiscard]] double calculate_energy_generation_rate(
double T9,
double rho,
double Ye,
double mue,
const std::vector<double>& Y,
const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const override;
[[nodiscard]] CppAD::AD<double> calculate_energy_generation_rate(
const CppAD::AD<double> &T9,
const CppAD::AD<double> &rho,
const CppAD::AD<double> &Ye,
const CppAD::AD<double> &mue,
const std::vector<CppAD::AD<double>> &Y,
const std::unordered_map<size_t, fourdst::atomic::Species> &index_to_species_map
) const override;
[[nodiscard]] double calculate_forward_rate_log_derivative(
double T9,
double rho,
double Ye,
double mue,
const fourdst::composition::Composition& composition
) const override;
[[nodiscard]] reaction::ReactionType type() const override { return reaction::ReactionType::WEAK; }
[[nodiscard]] std::unique_ptr<Reaction> clone() const override;
[[nodiscard]] bool is_reverse() const override { return false; };
private:
template<IsArithmeticOrAD T>
T calculate_rate(
T T9,
T rho,
T Ye,
T mue,
const std::vector<T> &Y,
const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const;
double get_log_rate_from_payload(const WeakRatePayload& payload) const;
private:
class AtomicWeakRate final : public CppAD::atomic_base<double> {
public:
AtomicWeakRate(
const WeakRateInterpolator& interpolator,
const size_t a,
const size_t z,
const WeakReactionType type
) :
CppAD::atomic_base<double>(std::format("atomic-{}-{}-weak-rate", a, z)),
m_interpolator(interpolator),
m_a(a),
m_z(z) ,
m_type(type) {}
bool forward(
size_t p,
size_t q,
const CppAD::vector<bool>& vx,
CppAD::vector<bool>& vy,
const CppAD::vector<double>& tx,
CppAD::vector<double>& ty
) override;
bool reverse(
size_t q,
const CppAD::vector<double>& tx,
const CppAD::vector<double>& ty,
CppAD::vector<double>& px,
const CppAD::vector<double>& py
) override;
bool for_sparse_jac(
size_t q,
const CppAD::vector<std::set<size_t>>&r,
CppAD::vector<std::set<size_t>>& s
) override;
bool rev_sparse_jac(
size_t q,
const CppAD::vector<std::set<size_t>>&rt,
CppAD::vector<std::set<size_t>>& st
) override;
private:
const WeakRateInterpolator& m_interpolator;
const size_t m_a;
const size_t m_z;
const WeakReactionType m_type;
};
struct constants {
const fourdst::constant::Constants& c = fourdst::constant::Constants::getInstance();
fourdst::constant::Constant neutronMassG = c.get("mN");
fourdst::constant::Constant protonMassG = c.get("mP");
fourdst::constant::Constant electronMassG = c.get("mE");
fourdst::constant::Constant speedOfLight = c.get("c");
fourdst::constant::Constant eVgRelation = c.get("eV_kg"); // note that despite the symbol this is in g NOT kg
fourdst::constant::Constant MeV2Erg = c.get("MeV_to_erg");
fourdst::constant::Constant amu = c.get("u");
double MeVgRelation = eVgRelation.value * 1.0e6;
double MeVPerGraph = 1.0/MeVgRelation;
double neutronMassMeV = neutronMassG.value * MeVgRelation;
double protonMassMeV = protonMassG.value * MeVgRelation;
double electronMassMeV = electronMassG.value * MeVgRelation;
double u_to_MeV = (amu.value * speedOfLight.value * speedOfLight.value)/MeV2Erg.value;
};
private:
const constants m_constants;
fourdst::atomic::Species m_reactant;
fourdst::atomic::Species m_product;
size_t m_reactant_a;
size_t m_reactant_z;
size_t m_product_a;
size_t m_product_z;
std::string m_id;
WeakReactionType m_type;
const WeakRateInterpolator& m_interpolator;
AtomicWeakRate m_atomic;
};
template<IsArithmeticOrAD T>
T WeakReaction::calculate_rate(
T T9,
T rho,
T Ye,
T mue,
const std::vector<T> &Y,
const std::unordered_map<size_t, fourdst::atomic::Species>& index_to_species_map
) const {
T log_rhoYe = CppAD::log10(rho * Ye);
T rateConstant = static_cast<T>(0.0);
if constexpr (std::is_same_v<T, CppAD::AD<double>>) { // Case where T is an AD type
std::vector<T> ax = {T9, log_rhoYe, mue};
std::vector<T> ay(1);
m_atomic(ax, ay);
rateConstant = static_cast<T>(ay[0]);
} else { // The case where T is of type double
const std::expected<WeakRatePayload, InterpolationError> result = m_interpolator.get_rates(
static_cast<uint16_t>(m_reactant_a),
static_cast<uint8_t>(m_reactant_z),
T9,
log_rhoYe,
mue
);
if (!result.has_value()) {
const InterpolationErrorType type = result.error().type;
const std::string msg = std::format(
"Failed to interpolate weak rate for (A={}, Z={}) at T9={}, log10(rho*Ye)={}, mu_e={} with error: {}",
m_reactant.name(), m_reactant_a, m_reactant_z, T9, log_rhoYe, mue, InterpolationErrorTypeMap.at(type)
);
throw std::runtime_error(msg);
}
const WeakRatePayload payload = result.value();
const double logRate = get_log_rate_from_payload(payload);
if (logRate <= GRIDFIRE_WEAK_REACTION_LIB_SENTINEL) {
rateConstant = static_cast<T>(0.0);
} else {
rateConstant = CppAD::pow(10.0, logRate);
}
}
return rateConstant;
}
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "gridfire/reaction/weak/weak_types.h"
#include "fourdst/composition/atomicSpecies.h"
#include <unordered_map>
#include <cstdint>
#include <vector>
#include <expected>
namespace gridfire::rates::weak {
class WeakRateInterpolator {
public:
using RowDataTable = std::array<RateDataRow, 77400>; // Total number of entries in the weak rate table NOTE: THIS MUST EQUAL THE VALUE IN weak_rate_library.h
explicit WeakRateInterpolator(const RowDataTable& raw_data);
[[nodiscard]] std::vector<fourdst::atomic::Species> available_isotopes() const;
[[nodiscard]] std::expected<WeakRatePayload, InterpolationError> get_rates(
uint16_t A,
uint8_t Z,
double t9,
double log_rhoYe,
double mu_e
) const;
[[nodiscard]] std::expected<WeakRateDerivatives, InterpolationError> get_rate_derivatives(
uint16_t A,
uint8_t Z,
double t9,
double log_rhoYe,
double mu_e
) const;
private:
static uint32_t pack_isotope_id(uint16_t A, uint8_t Z);
std::unordered_map<uint32_t, IsotopeGrid> m_rate_table;
};
}

View File

@@ -8,25 +8,10 @@
#include <array>
#include <cstdint>
#include "gridfire/reaction/weak/weak.h"
namespace gridfire::rates::weak {
// Represents a single row from the unified weak rate table
struct RateDataRow {
uint16_t A;
uint8_t Z;
float t9;
float log_rhoye;
float mu_e;
float log_beta_plus;
float log_electron_capture;
float log_neutrino_loss_ec;
float log_beta_minus;
float log_positron_capture;
float log_antineutrino_loss_bd;
};
// The complete, pre-processed weak rate table data
static constexpr std::array<RateDataRow, 77400> UNIFIED_WEAK_DATA = {
RateDataRow(6, 3, 0.01, 5.0, 0.485, -60.0, -60.0, -60.0, -60.0, -60.0, -60.0),

View File

@@ -0,0 +1,133 @@
#pragma once
#include <cstdint>
#include <array>
#include <vector>
#include <optional>
#include <unordered_map>
#include <ostream>
namespace gridfire::rates::weak {
struct RateDataRow {
uint16_t A;
uint8_t Z;
float t9;
float log_rhoye;
float mu_e;
float log_beta_plus;
float log_electron_capture;
float log_neutrino_loss_ec;
float log_beta_minus;
float log_positron_capture;
float log_antineutrino_loss_bd;
};
enum class WeakReactionType {
BETA_PLUS_DECAY,
BETA_MINUS_DECAY,
ELECTRON_CAPTURE,
POSITRON_CAPTURE,
};
enum class NeutrinoTypes {
ELECTRON_NEUTRINO,
ELECTRON_ANTINEUTRINO,
MUON_NEUTRINO,
MUON_ANTINEUTRINO,
TAU_NEUTRINO,
TAU_ANTINEUTRINO
};
enum class WeakMapError {
SPECIES_NOT_FOUND,
UNKNOWN_ERROR
};
struct WeakRatePayload {
double log_beta_plus;
double log_electron_capture;
double log_neutrino_loss_ec;
double log_beta_minus;
double log_positron_capture;
double log_antineutrino_loss_bd;
};
struct WeakRateDerivatives {
// Each array holds [d/dT9, d/dlogRhoYe, d/dMuE]
std::array<double, 3> d_log_beta_plus;
std::array<double, 3> d_log_electron_capture;
std::array<double, 3> d_log_neutrino_loss_ec;
std::array<double, 3> d_log_beta_minus;
std::array<double, 3> d_log_positron_capture;
std::array<double, 3> d_log_antineutrino_loss_bd;
};
enum class InterpolationErrorType {
BOUNDS_ERROR,
UNKNOWN_SPECIES_ERROR,
UNKNOWN_ERROR
};
inline std::unordered_map<InterpolationErrorType, std::string_view> InterpolationErrorTypeMap = {
{InterpolationErrorType::BOUNDS_ERROR, "Bounds Error"},
{InterpolationErrorType::UNKNOWN_SPECIES_ERROR, "Unknown Species Error"},
{InterpolationErrorType::UNKNOWN_ERROR, "Unknown Error"}
};
enum class TableAxes {
T9,
LOG_RHOYE,
MUE
};
struct BoundsErrorInfo {
TableAxes axis;
double axisMinValue;
double axisMaxValue;
double queryValue;
};
struct InterpolationError {
InterpolationErrorType type;
std::optional<std::unordered_map<TableAxes, BoundsErrorInfo>> boundsErrorInfo = std::nullopt;
};
struct IsotopeGrid {
std::vector<double> t9_axis;
std::vector<double> rhoYe_axis;
std::vector<double> mue_axis;
// index = (i_t9 * logRhoYe_axis.size() + j_rhoYe) + mue_axis.size() + k_mue
std::vector<WeakRatePayload> data;
};
constexpr std::string_view weak_reaction_type_name(const WeakReactionType t) noexcept {
switch (t) {
case WeakReactionType::BETA_PLUS_DECAY: return "bp";
case WeakReactionType::BETA_MINUS_DECAY: return "bm";
case WeakReactionType::ELECTRON_CAPTURE: return "ec";
case WeakReactionType::POSITRON_CAPTURE: return "pc";
}
return "Unknown";
}
struct WeakReactionEntry {
WeakReactionType type;
float T9;
float log_rhoYe;
float mu_e;
float log_rate;
float log_neutrino_loss;
friend std::ostream& operator<<(std::ostream& os, const WeakReactionEntry& reaction) {
os << "WeakReactionEntry(type=" << weak_reaction_type_name(reaction.type)
<< ", T9=" << reaction.T9
<< ", log_rhoYe=" << reaction.log_rhoYe
<< ", mu_e=" << reaction.mu_e
<< ", log_rate=" << reaction.log_rate
<< ", log_neutrino_loss=" << reaction.log_neutrino_loss
<< ")";
return os;
}
};
}

View File

@@ -44,7 +44,7 @@ namespace gridfire::screening {
*
* @param reactions The set of logical reactions in the network.
* @param species A vector of all atomic species involved in the network.
* @param Y A vector of the molar abundances (mol/g) for each species.
* @param Y The current composition, providing molar abundances (mol/g) for each species.
* @param T9 The temperature in units of 10^9 K.
* @param rho The plasma density in g/cm^3.
* @return A vector of screening factors (dimensionless), one for each reaction
@@ -73,10 +73,10 @@ namespace gridfire::screening {
[[nodiscard]] virtual std::vector<double> calculateScreeningFactors(
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<double>& Y,
const double T9,
const double rho
) const = 0;
const std::vector<double> &Y,
double T9,
double rho
) const = 0;
/**
* @brief Calculates screening factors using CppAD types for automatic differentiation.
@@ -88,7 +88,7 @@ namespace gridfire::screening {
*
* @param reactions The set of logical reactions in the network.
* @param species A vector of all atomic species involved in the network.
* @param Y A vector of the molar abundances (mol/g) for each species, as AD types.
* @param Y The current composition, providing molar abundances (mol/g) for each species.
* @param T9 The temperature in units of 10^9 K, as an AD type.
* @param rho The plasma density in g/cm^3, as an AD type.
* @return A vector of screening factors (dimensionless), as AD types.
@@ -100,9 +100,9 @@ namespace gridfire::screening {
[[nodiscard]] virtual std::vector<ADDouble> calculateScreeningFactors(
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<ADDouble>& Y,
const ADDouble T9,
const ADDouble rho
const std::vector<CppAD::AD<double>> &Y,
ADDouble T9,
ADDouble rho
) const = 0;
};
}
}

View File

@@ -31,7 +31,7 @@ namespace gridfire::screening {
*
* @param reactions The set of logical reactions in the network.
* @param species A vector of all atomic species (unused).
* @param Y A vector of the molar abundances (unused).
* @param Y A vector of the molar abundances.
* @param T9 The temperature (unused).
* @param rho The plasma density (unused).
* @return A vector of doubles, with each element being 1.0, of the same
@@ -54,9 +54,9 @@ namespace gridfire::screening {
[[nodiscard]] std::vector<double> calculateScreeningFactors(
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<double>& Y,
const double T9,
const double rho
const std::vector<double> &Y,
double T9,
double rho
) const override;
/**
@@ -68,7 +68,7 @@ namespace gridfire::screening {
*
* @param reactions The set of logical reactions in the network.
* @param species A vector of all atomic species (unused).
* @param Y A vector of the molar abundances as AD types (unused).
* @param Y The current composition, providing molar abundances (mol/g) for each species (unused).
* @param T9 The temperature as an AD type (unused).
* @param rho The plasma density as an AD type (unused).
* @return A vector of ADDouble, with each element being 1.0, of the same
@@ -77,9 +77,9 @@ namespace gridfire::screening {
[[nodiscard]] std::vector<ADDouble> calculateScreeningFactors(
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<ADDouble>& Y,
const ADDouble T9,
const ADDouble rho
const std::vector<CppAD::AD<double>> &Y,
ADDouble T9,
ADDouble rho
) const override;
private:
/**
@@ -92,7 +92,7 @@ namespace gridfire::screening {
* @tparam T The numeric type, either `double` or `CppAD::AD<double>`.
* @param reactions The set of reactions for which to calculate factors.
* @param species A vector of all atomic species (unused).
* @param Y A vector of molar abundances (unused).
* @param Y The current molar composition (unused).
* @param T9 The temperature (unused).
* @param rho The density (unused).
* @return A vector of type `T` with all elements initialized to 1.0.
@@ -102,8 +102,8 @@ namespace gridfire::screening {
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<T>& Y,
const T T9,
const T rho
const T& T9,
const T& rho
) const;
};
@@ -117,7 +117,7 @@ namespace gridfire::screening {
* @tparam T The numeric type, either `double` or `CppAD::AD<double>`.
* @param reactions The set of reactions, used to determine the size of the output vector.
* @param species Unused parameter.
* @param Y Unused parameter.
* @param Y Unused parameter.`
* @param T9 Unused parameter.
* @param rho Unused parameter.
* @return A `std::vector<T>` of the same size as `reactions`, with all elements set to 1.0.
@@ -127,8 +127,8 @@ namespace gridfire::screening {
const reaction::ReactionSet &reactions,
const std::vector<fourdst::atomic::Species> &species,
const std::vector<T> &Y,
const T T9,
const T rho
const T& T9,
const T& rho
) const {
return std::vector<T>(reactions.size(), T(1.0)); // Bare screening returns 1.0 for all reactions
}

View File

@@ -39,7 +39,7 @@ namespace gridfire::screening {
std::vector<T> IntermediateScreeningModel::calculateFactors_impl(
const reaction::ReactionSet &reactions,
const std::vector<fourdst::atomic::Species> &species,
const std::vector<T> &Y,
const std::vector<T>& Y,
const T T9,
const T rho
) const {

View File

@@ -33,7 +33,7 @@ namespace gridfire::screening {
*
* @param reactions The set of logical reactions in the network.
* @param species A vector of all atomic species involved in the network.
* @param Y A vector of the molar abundances (mol/g) for each species.
* @param Y The composition object giving the current molar abundances.
* @param T9 The temperature in units of 10^9 K.
* @param rho The plasma density in g/cm^3.
* @return A vector of screening factors (dimensionless), one for each reaction.
@@ -50,9 +50,9 @@ namespace gridfire::screening {
[[nodiscard]] std::vector<double> calculateScreeningFactors(
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<double>& Y,
const double T9,
const double rho
const std::vector<double> &Y,
double T9,
double rho
) const override;
/**
@@ -64,7 +64,7 @@ namespace gridfire::screening {
*
* @param reactions The set of logical reactions in the network.
* @param species A vector of all atomic species involved in the network.
* @param Y A vector of the molar abundances as AD types.
* @param Y The composition object giving the current molar abundances.
* @param T9 The temperature as an AD type.
* @param rho The plasma density as an AD type.
* @return A vector of screening factors as AD types.
@@ -72,9 +72,9 @@ namespace gridfire::screening {
[[nodiscard]] std::vector<CppAD::AD<double>> calculateScreeningFactors(
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<CppAD::AD<double>>& Y,
const CppAD::AD<double> T9,
const CppAD::AD<double> rho
const std::vector<CppAD::AD<double>> &Y,
CppAD::AD<double> T9,
CppAD::AD<double> rho
) const override;
private:
/// @brief Logger instance for recording trace and debug information.
@@ -91,7 +91,7 @@ namespace gridfire::screening {
* @tparam T The numeric type, either `double` or `CppAD::AD<double>`.
* @param reactions The set of reactions.
* @param species A vector of all species in the network.
* @param Y A vector of molar abundances.
* @param Y The composition object with current molar abundances.
* @param T9 The temperature in 10^9 K.
* @param rho The density in g/cm^3.
* @return A vector of screening factors of type `T`.
@@ -101,8 +101,8 @@ namespace gridfire::screening {
const reaction::ReactionSet& reactions,
const std::vector<fourdst::atomic::Species>& species,
const std::vector<T>& Y,
const T T9,
const T rho
T T9,
T rho
) const;
};
@@ -115,7 +115,7 @@ namespace gridfire::screening {
* @tparam T The numeric type (`double` or `CppAD::AD<double>`).
* @param reactions The set of reactions to be screened.
* @param species The list of all species in the network.
* @param Y The molar abundances of the species.
* @param Y The composition object providing current molar abundances.
* @param T9 The temperature in 10^9 K.
* @param rho The density in g/cm^3.
* @return A vector of screening factors, one for each reaction.

View File

@@ -1,14 +1,8 @@
#pragma once
#include "gridfire/engine/engine_graph.h"
#include "gridfire/engine/engine_abstract.h"
#include "gridfire/network.h"
#include "fourdst/logging/logging.h"
#include "fourdst/config/config.h"
#include "quill/Logger.h"
#include <functional>
#include <any>
#include <vector>
@@ -101,249 +95,4 @@ namespace gridfire::solver {
* @brief Type alias for a network solver strategy that uses a DynamicEngine.
*/
using DynamicNetworkSolverStrategy = NetworkSolverStrategy<DynamicEngine>;
/**
* @class DirectNetworkSolver
* @brief A network solver that directly integrates the reaction network ODEs.
*
* This solver uses a Runge-Kutta method to directly integrate the reaction network
* ODEs. It is simpler than the QSENetworkSolver, but it can be less efficient for
* stiff networks with disparate timescales.
*
* @implements DynamicNetworkSolverStrategy
*/
class DirectNetworkSolver final : public DynamicNetworkSolverStrategy {
public:
/**
* @brief Constructor for the DirectNetworkSolver.
* @param engine The dynamic engine to use for evaluating the network.
*/
using DynamicNetworkSolverStrategy::DynamicNetworkSolverStrategy;
/**
* @struct TimestepContext
* @brief Context for the timestep callback function for the DirectNetworkSolver.
*
* This struct contains the context that will be passed to the callback function at the end of each timestep.
* It includes the current time, state, timestep size, cached results, and other relevant information.
*
* This type should be used when defining a callback function
*
* **Example:**
* @code
* #include "gridfire/solver/solver.h"
*
* #include <ofstream>
* #include <ranges>
*
* static std::ofstream consumptionFile("consumption.txt");
* void callback(const gridfire::solver::DirectNetworkSolver::TimestepContext& context) {
* int H1Index = context.engine.getSpeciesIndex(fourdst::atomic::H_1);
* int He4Index = context.engine.getSpeciesIndex(fourdst::atomic::He_4);
*
* consumptionFile << context.t << "," << context.state(H1Index) << "," << context.state(He4Index) << "\n";
* }
*
* int main() {
* ... // Code to set up engine and solvers...
* solver.set_callback(callback);
* solver.evaluate(netIn);
* consumptionFile.close();
* }
* @endcode
*/
struct TimestepContext final : public SolverContextBase {
const double t; ///< Current time.
const boost::numeric::ublas::vector<double>& state; ///< Current state of the system.
const double dt; ///< Time step size.
const double cached_time; ///< Cached time for the last observed state.
const double last_observed_time; ///< Last time the state was observed.
const double last_step_time; ///< Last step time.
const double T9; ///< Temperature in units of 10^9 K.
const double rho; ///< Density in g/cm^3.
const std::optional<StepDerivatives<double>>& cached_result; ///< Cached result of the step derivatives.
const int num_steps; ///< Total number of steps taken.
const DynamicEngine& engine; ///< Reference to the dynamic engine.
const std::vector<fourdst::atomic::Species>& networkSpecies;
TimestepContext(
const double t,
const boost::numeric::ublas::vector<double> &state,
const double dt,
const double cached_time,
const double last_observed_time,
const double last_step_time,
const double t9,
const double rho,
const std::optional<StepDerivatives<double>> &cached_result,
const int num_steps,
const DynamicEngine &engine,
const std::vector<fourdst::atomic::Species>& networkSpecies
);
/**
* @brief Describe the context for callback functions.
* @return A vector of tuples, each containing a string for the parameter's name and a string for its type.
*
* This method provides a description of the context that will be passed to the callback function.
* The intent is that an end user can investigate the context and use this information to craft their own
* callback function.
*
* @implements SolverContextBase::describe
*/
[[nodiscard]] std::vector<std::tuple<std::string, std::string>> describe() const override;
};
/**
* @brief Type alias for a timestep callback function.
*
* @brief The type alias for the callback function that will be called at the end of each timestep.
*
*/
using TimestepCallback = std::function<void(const TimestepContext& context)>; ///< Type alias for a timestep callback function.
/**
* @brief Evaluates the network for a given timestep using direct integration.
* @param netIn The input conditions for the network.
* @return The output conditions after the timestep.
*/
NetOut evaluate(const NetIn& netIn) override;
/**
* @brief Sets the callback function to be called at the end of each timestep.
* @param callback The callback function to be called at the end of each timestep.
*
* This function allows the user to set a callback function that will be called at the end of each timestep.
* The callback function will receive a gridfire::solver::DirectNetworkSolver::TimestepContext object.
*/
void set_callback(const std::any &callback) override;
/**
* @brief Describe the context that will be passed to the callback function.
* @return A vector of tuples, each containing a string for the parameter's name and a string for its type.
*
* This method provides a description of the context that will be passed to the callback function.
* The intent is that an end user can investigate the context and use this information to craft their own
* callback function.
*
* @implements SolverContextBase::describe
*/
[[nodiscard]] std::vector<std::tuple<std::string, std::string>> describe_callback_context() const override;
private:
/**
* @struct RHSManager
* @brief Functor for calculating the right-hand side of the ODEs.
*
* This functor is used by the ODE solver to calculate the time derivatives of the
* species abundances. It takes the current abundances as input and returns the
* time derivatives.
*/
struct RHSManager {
DynamicEngine& m_engine; ///< The engine used to evaluate the network.
const double m_T9; ///< Temperature in units of 10^9 K.
const double m_rho; ///< Density in g/cm^3.
mutable double m_cached_time;
mutable std::optional<StepDerivatives<double>> m_cached_result;
mutable double m_last_observed_time = 0.0; ///< Last time the state was observed.
quill::Logger* m_logger = LogManager::getInstance().newFileLogger("integration.log", "GridFire"); ///< Logger instance.
mutable int m_num_steps = 0;
mutable double m_last_step_time = 1e-20;
TimestepCallback& m_callback;
const std::vector<fourdst::atomic::Species>& m_networkSpecies;
/**
* @brief Constructor for the RHSFunctor.
* @param engine The engine used to evaluate the network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
* @param callback callback function to be called at the end of each timestep.
* @param networkSpecies vector of species in the network in the correct order.
*/
RHSManager(
DynamicEngine& engine,
const double T9,
const double rho,
TimestepCallback& callback,
const std::vector<fourdst::atomic::Species>& networkSpecies
) :
m_engine(engine),
m_T9(T9),
m_rho(rho),
m_cached_time(0),
m_callback(callback),
m_networkSpecies(networkSpecies){}
/**
* @brief Calculates the time derivatives of the species abundances.
* @param Y Vector of current abundances.
* @param dYdt Vector to store the time derivatives.
* @param t Current time.
*/
void operator()(
const boost::numeric::ublas::vector<double>& Y,
boost::numeric::ublas::vector<double>& dYdt,
double t
) const;
void observe(const boost::numeric::ublas::vector<double>& state, double t) const;
void compute_and_cache(const boost::numeric::ublas::vector<double>& state, double t) const;
};
/**
* @struct JacobianFunctor
* @brief Functor for calculating the Jacobian matrix.
*
* This functor is used by the ODE solver to calculate the Jacobian matrix of the
* ODEs. It takes the current abundances as input and returns the Jacobian matrix.
*/
struct JacobianFunctor {
DynamicEngine& m_engine; ///< The engine used to evaluate the network.
const double m_T9; ///< Temperature in units of 10^9 K.
const double m_rho; ///< Density in g/cm^3.
/**
* @brief Constructor for the JacobianFunctor.
* @param engine The engine used to evaluate the network.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density in g/cm^3.
*/
JacobianFunctor(
DynamicEngine& engine,
const double T9,
const double rho
) :
m_engine(engine),
m_T9(T9),
m_rho(rho) {}
/**
* @brief Calculates the Jacobian matrix.
* @param Y Vector of current abundances.
* @param J Matrix to store the Jacobian matrix.
* @param t Current time.
* @param dfdt Vector to store the time derivatives (not used).
*/
void operator()(
const boost::numeric::ublas::vector<double>& Y,
boost::numeric::ublas::matrix<double>& J,
double t,
boost::numeric::ublas::vector<double>& dfdt
) const;
};
private:
quill::Logger* m_logger = LogManager::getInstance().getLogger("log"); ///< Logger instance.
Config& m_config = Config::getInstance(); ///< Configuration instance.
TimestepCallback m_callback;
};
}

View File

@@ -55,7 +55,7 @@ namespace gridfire::solver {
void set_callback(const std::any &callback) override;
bool get_stdout_logging_enabled() const;
[[nodiscard]] bool get_stdout_logging_enabled() const;
void set_stdout_logging_enabled(const bool value);
@@ -69,14 +69,14 @@ namespace gridfire::solver {
const double last_step_time;
const double T9;
const double rho;
const int num_steps;
const size_t num_steps;
const DynamicEngine& engine;
const std::vector<fourdst::atomic::Species>& networkSpecies;
// Constructor
TimestepContext(
double t, const N_Vector& state, double dt, double last_step_time,
double t9, double rho, int num_steps, const DynamicEngine& engine,
double t9, double rho, size_t num_steps, const DynamicEngine& engine,
const std::vector<fourdst::atomic::Species>& networkSpecies
);
@@ -104,8 +104,8 @@ namespace gridfire::solver {
};
private:
Config& m_config = Config::getInstance();
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
fourdst::config::Config& m_config = fourdst::config::Config::getInstance();
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
static int cvode_rhs_wrapper(sunrealtype t, N_Vector y, N_Vector ydot, void *user_data);
static int cvode_jac_wrapper(sunrealtype t, N_Vector y, N_Vector ydot, SUNMatrix J, void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);

View File

@@ -23,7 +23,7 @@ namespace gridfire::trigger::solver::CVODE {
size_t numTriggers() const override;
size_t numMisses() const override;
private:
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
mutable size_t m_hits = 0;
mutable size_t m_misses = 0;
mutable size_t m_updates = 0;
@@ -48,7 +48,7 @@ namespace gridfire::trigger::solver::CVODE {
size_t numTriggers() const override;
size_t numMisses() const override;
private:
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
mutable size_t m_hits = 0;
mutable size_t m_misses = 0;
mutable size_t m_updates = 0;
@@ -71,7 +71,7 @@ namespace gridfire::trigger::solver::CVODE {
size_t numTriggers() const override;
size_t numMisses() const override;
private:
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
mutable size_t m_hits = 0;
mutable size_t m_misses = 0;
mutable size_t m_updates = 0;

View File

@@ -5,7 +5,7 @@
#include <iostream>
namespace gridfire::trigger {
inline void printWhy(const TriggerResult& result, const int indent = 0) {
inline void printWhy(const TriggerResult& result, const int indent = 0) { // NOLINT(*-no-recursion)
const std::string prefix(indent * 2, ' ');
std::cout << prefix << "• [" << (result.value ? "TRUE" : "FALSE")
<< "] " << result.name << ": " << result.description << std::endl;

View File

@@ -3,7 +3,6 @@
#include "gridfire/trigger/trigger_result.h"
#include <string>
#include <unordered_map>
namespace gridfire::trigger {
template <typename TriggerContextStruct>
@@ -16,11 +15,11 @@ namespace gridfire::trigger {
virtual void update(const TriggerContextStruct& ctx) = 0;
virtual void reset() = 0;
virtual std::string name() const = 0;
virtual std::string describe() const = 0;
virtual TriggerResult why(const TriggerContextStruct& ctx) const = 0;
[[nodiscard]] virtual std::string name() const = 0;
[[nodiscard]] virtual std::string describe() const = 0;
[[nodiscard]] virtual TriggerResult why(const TriggerContextStruct& ctx) const = 0;
virtual size_t numTriggers() const = 0;
virtual size_t numMisses() const = 0;
[[nodiscard]] virtual size_t numTriggers() const = 0;
[[nodiscard]] virtual size_t numMisses() const = 0;
};
}

View File

@@ -4,11 +4,6 @@
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <iostream>
namespace gridfire::utils {
@@ -64,9 +59,9 @@ namespace gridfire::utils {
*/
std::string formatNuclearTimescaleLogString(
const DynamicEngine& engine,
const std::vector<double>& Y,
const double T9,
const double rho
const fourdst::composition::Composition& composition,
double T9,
double rho
);

View File

@@ -1,6 +1,7 @@
#pragma once
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <sstream>
@@ -15,20 +16,20 @@ namespace gridfire::utils {
public:
virtual ~ColumnBase() = default;
// Gets the string representation of the data at a given row
virtual std::string getCellData(size_t rowIndex) const = 0;
[[nodiscard]] virtual std::string getCellData(size_t rowIndex) const = 0;
// Gets the header text for the column
virtual std::string getHeader() const = 0;
[[nodiscard]] virtual std::string getHeader() const = 0;
// Gets the number of data rows in the column
virtual size_t getRowCount() const = 0;
[[nodiscard]] virtual size_t getRowCount() const = 0;
};
template<typename T>
class Column final : public ColumnBase {
public:
Column(const std::string& header, const std::vector<T>& data)
: m_header(header), m_data(data) {}
Column(std::string header, const std::vector<T>& data)
: m_header(std::move(header)), m_data(data) {}
std::string getCellData(size_t rowIndex) const override {
[[nodiscard]] std::string getCellData(size_t rowIndex) const override {
std::stringstream ss;
if (rowIndex < m_data.size()) {
ss << m_data[rowIndex];
@@ -36,11 +37,11 @@ namespace gridfire::utils {
return ss.str();
}
std::string getHeader() const override {
[[nodiscard]] std::string getHeader() const override {
return m_header;
}
size_t getRowCount() const override {
[[nodiscard]] size_t getRowCount() const override {
return m_data.size();
}
private:
@@ -74,8 +75,8 @@ namespace gridfire::utils {
std::stringstream table_ss;
// --- Table Title ---
size_t total_width = std::accumulate(col_widths.begin(), col_widths.end(), 0) + (num_cols * 3) + 1;
size_t title_padding = (total_width > tableName.length()) ? (total_width - tableName.length()) / 2 : 0;
const size_t total_width = std::accumulate(col_widths.begin(), col_widths.end(), 0) + (num_cols * 3) + 1; // NOLINT(*-fold-init-type)
const size_t title_padding = (total_width > tableName.length()) ? (total_width - tableName.length()) / 2 : 0;
table_ss << std::string(title_padding, ' ') << tableName << "\n";
// --- Helper to draw horizontal border ---
@@ -94,7 +95,7 @@ namespace gridfire::utils {
// --- Draw Header Row ---
table_ss << "|";
for (size_t j = 0; j < num_cols; ++j) {
table_ss << " " << std::left << std::setw(col_widths[j]) << columns[j]->getHeader() << " |";
table_ss << " " << std::left << std::setw(col_widths[j]) << columns[j]->getHeader() << " |"; // NOLINT(*-narrowing-conversions)
}
table_ss << "\n";
@@ -105,7 +106,7 @@ namespace gridfire::utils {
for (size_t i = 0; i < num_rows; ++i) {
table_ss << "|";
for (size_t j = 0; j < num_cols; ++j) {
table_ss << " " << std::left << std::setw(col_widths[j]) << columns[j]->getCellData(i) << " |";
table_ss << " " << std::left << std::setw(col_widths[j]) << columns[j]->getCellData(i) << " |"; // NOLINT(*-narrowing-conversions)
}
table_ss << "\n";
}