feat(neutrino): Started framework for neutrino loss

Neutrino loss is essential for neutrino cooling. Started adding
framework to track this. Reaclib reactions use a simple heuristic where
electron capture reactions loss 100% of their energy to neutrinos
whereas beta decay reactions loose 50% of their energy to neutrinos
This commit is contained in:
2025-11-27 14:34:20 -05:00
parent 7b67f3064a
commit 05175ae87c
13 changed files with 259 additions and 119 deletions

View File

@@ -54,6 +54,9 @@ namespace gridfire::engine {
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).
std::map<fourdst::atomic::Species, std::unordered_map<std::string, T>> reactionContributions{};
T neutrinoEnergyLossRate = T(0.0); // (erg/g/s)
T totalNeutrinoFlux = T(0.0); // (neutrinos/g/s)
StepDerivatives() : dydt(), nuclearEnergyGenerationRate(T(0.0)) {}
};

View File

@@ -778,6 +778,7 @@ namespace gridfire::engine {
const double Na = Constants::getInstance().get("N_a").value; ///< Avogadro's number.
const double c = Constants::getInstance().get("c").value; ///< Speed of light in cm/s.
const double kB = Constants::getInstance().get("kB").value; ///< Boltzmann constant in erg/K.
const double MeV_to_erg = Constants::getInstance().get("MeV_to_erg").value; ///< Conversion factor from MeV to erg.
};
enum class JacobianMatrixState {

View File

@@ -16,4 +16,12 @@ namespace gridfire::reaclib {
*/
const reaction::ReactionSet &get_all_reaclib_reactions();
// Simple heuristic to check if a reaclib reaction is a strong or weak reaction
/* A weak reaction is defined here as one where:
- The number of reactants is equal to the number of products
- There is only one reactant and one product
- The mass number (A) of the reactant is equal to the mass number (A) of the product
*/
bool reaction_is_weak(const reaction::Reaction& reaction);
} // namespace gridfire::reaclib

View File

@@ -27,19 +27,26 @@ namespace gridfire::reaction {
enum class ReactionType {
WEAK,
REACLIB,
REACLIB_WEAK,
LOGICAL_REACLIB,
LOGICAL_REACLIB_WEAK,
};
static std::unordered_map<ReactionType, std::string> ReactionTypeNames = {
{ReactionType::WEAK, "weak"},
{ReactionType::REACLIB, "reaclib"},
{ReactionType::REACLIB_WEAK, "reaclib_weak"},
{ReactionType::LOGICAL_REACLIB, "logical_reaclib"},
{ReactionType::LOGICAL_REACLIB_WEAK, "logical_reaclib_weak"},
};
static std::unordered_map<ReactionType, std::string> ReactionPhysicalTypeNames = {
{ReactionType::WEAK, "Weak"},
{ReactionType::REACLIB, "Strong"},
{ReactionType::LOGICAL_REACLIB, "Strong"},
{ReactionType::REACLIB_WEAK, "Weak"},
{ReactionType::LOGICAL_REACLIB_WEAK, "Weak"},
};
/**
* @struct RateCoefficientSet
@@ -363,7 +370,7 @@ namespace gridfire::reaction {
* @param reactants A vector of reactant species.
* @param products A vector of product species.
* @param qValue The Q-value of the reaction in MeV.
* @param label The source label for the rate data (e.g., "wc12", "st08").
* @param label The sources label for the rate data (e.g., "wc12", "st08").
* @param sets The set of rate coefficients.
* @param reverse True if this is a reverse reaction rate.
*/
@@ -645,6 +652,27 @@ namespace gridfire::reaction {
}
};
class WeakReaclibReaction final : public ReaclibReaction {
public:
using ReaclibReaction::ReaclibReaction;
[[nodiscard]] ReactionType type() const override { return ReactionType::REACLIB_WEAK; }
[[nodiscard]] std::unique_ptr<Reaction> clone() const override {
return std::make_unique<WeakReaclibReaction>(
m_id,
m_peName,
m_chapter,
reactants(),
products(),
m_qValue,
m_sourceLabel,
m_rateCoefficients,
m_reverse
);
}
};
/**
* @class LogicalReaclibReaction
@@ -664,7 +692,7 @@ namespace gridfire::reaction {
* @param reactions A vector of reactions that represent the same logical process.
* @throws std::runtime_error if the provided reactions have inconsistent Q-values.
*/
explicit LogicalReaclibReaction(const std::vector<ReaclibReaction> &reactions);
explicit LogicalReaclibReaction(const std::vector<std::unique_ptr<ReaclibReaction>> &reactions);
/**
* @breif Constructs a LogicalReaction from a vector of `Reaction` objects and allows the user
@@ -673,7 +701,7 @@ namespace gridfire::reaction {
* @param reverse A flag to control if this logical reaction is reverse or not
* @returns std::runtime_error if the provided reactions have inconsistent Q-values.
*/
explicit LogicalReaclibReaction(const std::vector<ReaclibReaction> &reactions, bool reverse);
explicit LogicalReaclibReaction(const std::vector<std::unique_ptr<ReaclibReaction>> &reactions, bool reverse);
/**
* @brief Adds another `Reaction` source to this logical reaction.
@@ -718,7 +746,12 @@ namespace gridfire::reaction {
double Ye, double mue, const fourdst::composition::Composition& comp
) const override;
[[nodiscard]] ReactionType type() const override { return ReactionType::LOGICAL_REACLIB; }
[[nodiscard]] ReactionType type() const override {
if (m_weak) {
return ReactionType::LOGICAL_REACLIB_WEAK;
}
return ReactionType::LOGICAL_REACLIB;
}
[[nodiscard]] std::unique_ptr<Reaction> clone() const override;
@@ -760,6 +793,7 @@ namespace gridfire::reaction {
private:
std::vector<std::string> m_sources; ///< List of source labels.
std::vector<RateCoefficientSet> m_rates; ///< List of rate coefficient sets from each source.
bool m_weak = false;
private:
/**

View File

@@ -232,10 +232,14 @@ namespace gridfire::solver {
const std::vector<fourdst::atomic::Species>* networkSpecies{};
std::unique_ptr<exceptions::EngineError> captured_exception = nullptr;
std::optional<std::map<fourdst::atomic::Species, std::unordered_map<std::string, double>>> reaction_contribution_map;
double neutrino_energy_loss_rate = 0.0;
double total_neutrino_flux = 0.0;
};
struct CVODERHSOutputData {
std::map<fourdst::atomic::Species, std::unordered_map<std::string, double>> reaction_contribution_map;
double neutrino_energy_loss_rate;
double total_neutrino_flux;
};
private:

View File

@@ -40,6 +40,8 @@ namespace gridfire {
double energy; ///< Energy in ergs after evaluation
double dEps_dT; ///< Partial derivative of energy generation rate with respect to temperature
double dEps_dRho; ///< Partial derivative of energy generation rate with respect to density
double neutrino_energy_loss_rate; ///< Neutrino energy loss rate in ergs/g/s
double total_neutrino_flux; ///< Total neutrino flux in neutrinos/g/s
friend std::ostream& operator<<(std::ostream& os, const NetOut& netOut) {
os << "NetOut(composition=" << netOut.composition << ", num_steps=" << netOut.num_steps << ", ε=" << netOut.energy << ", dε/dT=" << netOut.dEps_dT << ", dε/dρ=" << netOut.dEps_dRho << ")";