refactor(reaction): refactored to an abstract reaction class in prep for weak reactions
This commit is contained in:
@@ -26,7 +26,7 @@ std::string trim_whitespace(const std::string& str) {
|
||||
}
|
||||
|
||||
namespace gridfire::reaclib {
|
||||
static reaction::LogicalReactionSet* s_all_reaclib_reactions_ptr = nullptr;
|
||||
static reaction::ReactionSet* s_all_reaclib_reactions_ptr = nullptr;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct ReactionRecord {
|
||||
@@ -85,7 +85,7 @@ namespace gridfire::reaclib {
|
||||
const auto* records = reinterpret_cast<const ReactionRecord*>(raw_reactions_data);
|
||||
constexpr size_t num_reactions = raw_reactions_data_len / sizeof(ReactionRecord);
|
||||
|
||||
std::vector<reaction::Reaction> reaction_list;
|
||||
std::vector<std::unique_ptr<reaction::Reaction>> reaction_list;
|
||||
reaction_list.reserve(num_reactions);
|
||||
|
||||
for (size_t i = 0; i < num_reactions; ++i) {
|
||||
@@ -108,7 +108,7 @@ namespace gridfire::reaclib {
|
||||
};
|
||||
|
||||
// Construct the Reaction object. We use rpName for both the unique ID and the human-readable name.
|
||||
reaction_list.emplace_back(
|
||||
reaction_list.emplace_back(std::make_unique<reaction::ReaclibReaction>(
|
||||
rpName_sv,
|
||||
rpName_sv,
|
||||
chapter,
|
||||
@@ -118,15 +118,15 @@ namespace gridfire::reaclib {
|
||||
label_sv,
|
||||
rate_coeffs,
|
||||
reverse
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
// The ReactionSet takes the vector of all individual reactions.
|
||||
const reaction::ReactionSet reaction_set(std::move(reaction_list));
|
||||
|
||||
// The LogicalReactionSet groups reactions by their peName, which is what we want.
|
||||
s_all_reaclib_reactions_ptr = new reaction::LogicalReactionSet(
|
||||
reaction::packReactionSetToLogicalReactionSet(reaction_set)
|
||||
s_all_reaclib_reactions_ptr = new reaction::ReactionSet(
|
||||
reaction::packReactionSet(reaction_set)
|
||||
);
|
||||
|
||||
s_initialized = true;
|
||||
@@ -135,7 +135,7 @@ namespace gridfire::reaclib {
|
||||
|
||||
// --- Public Interface Implementation ---
|
||||
|
||||
const reaction::LogicalReactionSet& get_all_reactions() {
|
||||
const reaction::ReactionSet &get_all_reaclib_reactions() {
|
||||
// This ensures that the initialization happens only on the first call.
|
||||
if (!s_initialized) {
|
||||
initializeAllReaclibReactions();
|
||||
|
||||
@@ -13,10 +13,19 @@
|
||||
|
||||
#include "xxhash64.h"
|
||||
|
||||
namespace {
|
||||
std::string_view safe_check_reactant_id(const std::vector<gridfire::reaction::ReaclibReaction>& reactions) {
|
||||
if (reactions.empty()) {
|
||||
throw std::runtime_error("No reactions found in the REACLIB reaction set.");
|
||||
}
|
||||
return reactions.front().peName();
|
||||
}
|
||||
}
|
||||
|
||||
namespace gridfire::reaction {
|
||||
using namespace fourdst::atomic;
|
||||
|
||||
Reaction::Reaction(
|
||||
ReaclibReaction::ReaclibReaction(
|
||||
const std::string_view id,
|
||||
const std::string_view peName,
|
||||
const int chapter,
|
||||
@@ -36,15 +45,15 @@ namespace gridfire::reaction {
|
||||
m_rateCoefficients(sets),
|
||||
m_reverse(reverse) {}
|
||||
|
||||
double Reaction::calculate_rate(const double T9) const {
|
||||
double ReaclibReaction::calculate_rate(const double T9, const double rho, const std::vector<double>& Y) const {
|
||||
return calculate_rate<double>(T9);
|
||||
}
|
||||
|
||||
CppAD::AD<double> Reaction::calculate_rate(const CppAD::AD<double> T9) const {
|
||||
CppAD::AD<double> ReaclibReaction::calculate_rate(const CppAD::AD<double> T9, const CppAD::AD<double> rho, const std::vector<CppAD::AD<double>>& Y) const {
|
||||
return calculate_rate<CppAD::AD<double>>(T9);
|
||||
}
|
||||
|
||||
double Reaction::calculate_forward_rate_log_derivative(const double T9) const {
|
||||
double ReaclibReaction::calculate_forward_rate_log_derivative(const double T9, const double rho, const std::vector<double>& Y) const {
|
||||
constexpr double r_p13 = 1.0 / 3.0;
|
||||
constexpr double r_p53 = 5.0 / 3.0;
|
||||
constexpr double r_p23 = 2.0 / 3.0;
|
||||
@@ -65,12 +74,12 @@ namespace gridfire::reaction {
|
||||
return d_log_k_fwd_dT9; // Return the derivative of the log rate with respect to T9
|
||||
}
|
||||
|
||||
bool Reaction::contains(const Species &species) const {
|
||||
bool ReaclibReaction::contains(const Species &species) const {
|
||||
return contains_reactant(species) || contains_product(species);
|
||||
}
|
||||
|
||||
|
||||
bool Reaction::contains_reactant(const Species& species) const {
|
||||
bool ReaclibReaction::contains_reactant(const Species& species) const {
|
||||
for (const auto& reactant : m_reactants) {
|
||||
if (reactant == species) {
|
||||
return true;
|
||||
@@ -79,7 +88,7 @@ namespace gridfire::reaction {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Reaction::contains_product(const Species& species) const {
|
||||
bool ReaclibReaction::contains_product(const Species& species) const {
|
||||
for (const auto& product : m_products) {
|
||||
if (product == species) {
|
||||
return true;
|
||||
@@ -88,14 +97,14 @@ namespace gridfire::reaction {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_set<Species> Reaction::all_species() const {
|
||||
std::unordered_set<Species> ReaclibReaction::all_species() const {
|
||||
auto rs = reactant_species();
|
||||
auto ps = product_species();
|
||||
rs.insert(ps.begin(), ps.end());
|
||||
return rs;
|
||||
}
|
||||
|
||||
std::unordered_set<Species> Reaction::reactant_species() const {
|
||||
std::unordered_set<Species> ReaclibReaction::reactant_species() const {
|
||||
std::unordered_set<Species> reactantsSet;
|
||||
for (const auto& reactant : m_reactants) {
|
||||
reactantsSet.insert(reactant);
|
||||
@@ -103,7 +112,7 @@ namespace gridfire::reaction {
|
||||
return reactantsSet;
|
||||
}
|
||||
|
||||
std::unordered_set<Species> Reaction::product_species() const {
|
||||
std::unordered_set<Species> ReaclibReaction::product_species() const {
|
||||
std::unordered_set<Species> productsSet;
|
||||
for (const auto& product : m_products) {
|
||||
productsSet.insert(product);
|
||||
@@ -111,7 +120,7 @@ namespace gridfire::reaction {
|
||||
return productsSet;
|
||||
}
|
||||
|
||||
int Reaction::stoichiometry(const Species& species) const {
|
||||
int ReaclibReaction::stoichiometry(const Species& species) const {
|
||||
int s = 0;
|
||||
for (const auto& reactant : m_reactants) {
|
||||
if (reactant == species) {
|
||||
@@ -126,11 +135,11 @@ namespace gridfire::reaction {
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Reaction::num_species() const {
|
||||
size_t ReaclibReaction::num_species() const {
|
||||
return all_species().size();
|
||||
}
|
||||
|
||||
std::unordered_map<Species, int> Reaction::stoichiometry() const {
|
||||
std::unordered_map<Species, int> ReaclibReaction::stoichiometry() const {
|
||||
std::unordered_map<Species, int> stoichiometryMap;
|
||||
for (const auto& reactant : m_reactants) {
|
||||
stoichiometryMap[reactant]--;
|
||||
@@ -141,7 +150,7 @@ namespace gridfire::reaction {
|
||||
return stoichiometryMap;
|
||||
}
|
||||
|
||||
double Reaction::excess_energy() const {
|
||||
double ReaclibReaction::excess_energy() const {
|
||||
double reactantMass = 0.0;
|
||||
double productMass = 0.0;
|
||||
constexpr double AMU2MeV = 931.494893; // Conversion factor from atomic mass unit to MeV
|
||||
@@ -154,14 +163,18 @@ namespace gridfire::reaction {
|
||||
return (reactantMass - productMass) * AMU2MeV;
|
||||
}
|
||||
|
||||
uint64_t Reaction::hash(const uint64_t seed) const {
|
||||
uint64_t ReaclibReaction::hash(const uint64_t seed) const {
|
||||
return XXHash64::hash(m_id.data(), m_id.size(), seed);
|
||||
}
|
||||
|
||||
std::unique_ptr<Reaction> ReaclibReaction::clone() const {
|
||||
return std::make_unique<ReaclibReaction>(*this);
|
||||
}
|
||||
|
||||
|
||||
LogicalReaction::LogicalReaction(const std::vector<Reaction>& reactants) :
|
||||
Reaction(reactants.front().peName(),
|
||||
LogicalReaclibReaction::LogicalReaclibReaction(const std::vector<ReaclibReaction>& reactants) :
|
||||
ReaclibReaction(
|
||||
safe_check_reactant_id(reactants), // Use this first to check if the reactants array is empty and safely exit if so
|
||||
reactants.front().peName(),
|
||||
reactants.front().chapter(),
|
||||
reactants.front().reactants(),
|
||||
@@ -177,45 +190,45 @@ namespace gridfire::reaction {
|
||||
if (std::abs(std::abs(reaction.qValue()) - std::abs(m_qValue)) > 1e-6) {
|
||||
LOG_ERROR(
|
||||
m_logger,
|
||||
"LogicalReaction constructed with reactions having different Q-values. Expected {} got {}.",
|
||||
"LogicalReaclibReaction constructed with reactions having different Q-values. Expected {} got {}.",
|
||||
m_qValue,
|
||||
reaction.qValue()
|
||||
);
|
||||
m_logger -> flush_log();
|
||||
throw std::runtime_error("LogicalReaction constructed with reactions having different Q-values. Expected " + std::to_string(m_qValue) + " got " + std::to_string(reaction.qValue()) + " (difference : " + std::to_string(std::abs(reaction.qValue() - m_qValue)) + ").");
|
||||
throw std::runtime_error("LogicalReaclibReaction constructed with reactions having different Q-values. Expected " + std::to_string(m_qValue) + " got " + std::to_string(reaction.qValue()) + " (difference : " + std::to_string(std::abs(reaction.qValue() - m_qValue)) + ").");
|
||||
}
|
||||
m_sources.push_back(std::string(reaction.sourceLabel()));
|
||||
m_sources.emplace_back(reaction.sourceLabel());
|
||||
m_rates.push_back(reaction.rateCoefficients());
|
||||
}
|
||||
}
|
||||
|
||||
void LogicalReaction::add_reaction(const Reaction& reaction) {
|
||||
void LogicalReaclibReaction::add_reaction(const ReaclibReaction& reaction) {
|
||||
if (reaction.peName() != m_id) {
|
||||
LOG_ERROR(m_logger, "Cannot add reaction with different peName to LogicalReaction. Expected {} got {}.", m_id, reaction.peName());
|
||||
LOG_ERROR(m_logger, "Cannot add reaction with different peName to LogicalReaclibReaction. Expected {} got {}.", m_id, reaction.peName());
|
||||
m_logger -> flush_log();
|
||||
throw std::runtime_error("Cannot add reaction with different peName to LogicalReaction. Expected " + std::string(m_id) + " got " + std::string(reaction.peName()) + ".");
|
||||
throw std::runtime_error("Cannot add reaction with different peName to LogicalReaclibReaction. Expected " + std::string(m_id) + " got " + std::string(reaction.peName()) + ".");
|
||||
}
|
||||
for (const auto& source : m_sources) {
|
||||
if (source == reaction.sourceLabel()) {
|
||||
LOG_ERROR(m_logger, "Cannot add reaction with duplicate source label {} to LogicalReaction.", reaction.sourceLabel());
|
||||
LOG_ERROR(m_logger, "Cannot add reaction with duplicate source label {} to LogicalReaclibReaction.", reaction.sourceLabel());
|
||||
m_logger -> flush_log();
|
||||
throw std::runtime_error("Cannot add reaction with duplicate source label " + std::string(reaction.sourceLabel()) + " to LogicalReaction.");
|
||||
throw std::runtime_error("Cannot add reaction with duplicate source label " + std::string(reaction.sourceLabel()) + " to LogicalReaclibReaction.");
|
||||
}
|
||||
}
|
||||
if (std::abs(reaction.qValue() - m_qValue) > 1e-6) {
|
||||
LOG_ERROR(m_logger, "LogicalReaction constructed with reactions having different Q-values. Expected {} got {}.", m_qValue, reaction.qValue());
|
||||
LOG_ERROR(m_logger, "LogicalReaclibReaction constructed with reactions having different Q-values. Expected {} got {}.", m_qValue, reaction.qValue());
|
||||
m_logger -> flush_log();
|
||||
throw std::runtime_error("LogicalReaction constructed with reactions having different Q-values. Expected " + std::to_string(m_qValue) + " got " + std::to_string(reaction.qValue()) + ".");
|
||||
throw std::runtime_error("LogicalReaclibReaction constructed with reactions having different Q-values. Expected " + std::to_string(m_qValue) + " got " + std::to_string(reaction.qValue()) + ".");
|
||||
}
|
||||
m_sources.push_back(std::string(reaction.sourceLabel()));
|
||||
m_sources.emplace_back(reaction.sourceLabel());
|
||||
m_rates.push_back(reaction.rateCoefficients());
|
||||
}
|
||||
|
||||
double LogicalReaction::calculate_rate(const double T9) const {
|
||||
double LogicalReaclibReaction::calculate_rate(const double T9, const double rho, const std::vector<double>& Y) const {
|
||||
return calculate_rate<double>(T9);
|
||||
}
|
||||
|
||||
double LogicalReaction::calculate_forward_rate_log_derivative(const double T9) const {
|
||||
double LogicalReaclibReaction::calculate_forward_rate_log_derivative(const double T9, const double rho, const std::vector<double>& Y) const {
|
||||
constexpr double r_p13 = 1.0 / 3.0;
|
||||
constexpr double r_p53 = 5.0 / 3.0;
|
||||
constexpr double r_p23 = 2.0 / 3.0;
|
||||
@@ -266,26 +279,258 @@ namespace gridfire::reaction {
|
||||
return totalRateDerivative / totalRate;
|
||||
}
|
||||
|
||||
CppAD::AD<double> LogicalReaction::calculate_rate(const CppAD::AD<double> T9) const {
|
||||
std::unique_ptr<Reaction> LogicalReaclibReaction::clone() const {
|
||||
return std::make_unique<LogicalReaclibReaction>(*this);
|
||||
}
|
||||
|
||||
CppAD::AD<double> LogicalReaclibReaction::calculate_rate(
|
||||
const CppAD::AD<double> T9,
|
||||
const CppAD::AD<double> rho,
|
||||
const std::vector<CppAD::AD<double>>& Y
|
||||
) const {
|
||||
return calculate_rate<CppAD::AD<double>>(T9);
|
||||
}
|
||||
|
||||
LogicalReactionSet packReactionSetToLogicalReactionSet(const ReactionSet& reactionSet) {
|
||||
std::unordered_map<std::string_view, std::vector<Reaction>> groupedReactions;
|
||||
|
||||
for (const auto& reaction: reactionSet) {
|
||||
groupedReactions[reaction.peName()].push_back(reaction);
|
||||
ReactionSet::ReactionSet(
|
||||
std::vector<std::unique_ptr<Reaction>>&& reactions
|
||||
) :
|
||||
m_reactions(std::move(reactions)) {
|
||||
if (m_reactions.empty()) {
|
||||
return; // Case where the reactions will be added later.
|
||||
}
|
||||
|
||||
std::vector<LogicalReaction> reactions;
|
||||
reactions.reserve(groupedReactions.size());
|
||||
|
||||
for (const auto &reactionsGroup: groupedReactions | std::views::values) {
|
||||
LogicalReaction logicalReaction(reactionsGroup);
|
||||
reactions.push_back(logicalReaction);
|
||||
m_reactionNameMap.reserve(reactions.size());
|
||||
size_t i = 0;
|
||||
for (const auto& reaction : m_reactions) {
|
||||
m_id += reaction->id();
|
||||
m_reactionNameMap.emplace(std::string(reaction->id()), i);
|
||||
i++;
|
||||
}
|
||||
return LogicalReactionSet(std::move(reactions));
|
||||
}
|
||||
|
||||
ReactionSet::ReactionSet(const std::vector<Reaction *> &reactions) {
|
||||
m_reactions.reserve(reactions.size());
|
||||
m_reactionNameMap.reserve(reactions.size());
|
||||
size_t i = 0;
|
||||
for (const auto& reaction : reactions) {
|
||||
m_reactions.push_back(reaction->clone());
|
||||
m_id += reaction->id();
|
||||
m_reactionNameMap.emplace(std::string(reaction->id()), i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
ReactionSet::ReactionSet() = default;
|
||||
|
||||
ReactionSet::ReactionSet(const ReactionSet &other) {
|
||||
m_reactions.reserve(other.m_reactions.size());
|
||||
for (const auto& reaction: other.m_reactions) {
|
||||
m_reactions.push_back(reaction->clone());
|
||||
}
|
||||
|
||||
m_reactionNameMap.reserve(other.m_reactionNameMap.size());
|
||||
size_t i = 0;
|
||||
for (const auto& reaction : m_reactions) {
|
||||
m_reactionNameMap.emplace(std::string(reaction->id()), i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
ReactionSet& ReactionSet::operator=(const ReactionSet &other) {
|
||||
if (this != &other) {
|
||||
ReactionSet temp(other);
|
||||
std::swap(m_reactions, temp.m_reactions);
|
||||
std::swap(m_reactionNameMap, temp.m_reactionNameMap);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ReactionSet::add_reaction(const Reaction& reaction) {
|
||||
const std::size_t new_index = m_reactions.size();
|
||||
|
||||
auto reaction_id = std::string(reaction.id());
|
||||
|
||||
m_reactions.emplace_back(reaction.clone());
|
||||
m_id += reaction_id;
|
||||
|
||||
m_reactionNameMap.emplace(std::move(reaction_id), new_index);
|
||||
}
|
||||
|
||||
void ReactionSet::add_reaction(std::unique_ptr<Reaction>&& reaction) {
|
||||
const std::size_t new_index = m_reactionNameMap.size();
|
||||
|
||||
auto reaction_id = std::string(reaction->id());
|
||||
|
||||
m_reactions.emplace_back(std::move(reaction));
|
||||
|
||||
m_id += reaction_id;
|
||||
|
||||
m_reactionNameMap.emplace(std::move(reaction_id), new_index);
|
||||
}
|
||||
|
||||
void ReactionSet::remove_reaction(const Reaction& reaction) {
|
||||
const auto reaction_id = std::string(reaction.id());
|
||||
if (!m_reactionNameMap.contains(reaction_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::erase_if(m_reactions, [&reaction_id](const auto& r_ptr) {
|
||||
return r_ptr->id() == reaction_id;
|
||||
});
|
||||
|
||||
m_reactionNameMap.clear();
|
||||
m_reactionNameMap.reserve(m_reactions.size());
|
||||
for (size_t i = 0; i < m_reactions.size(); ++i) {
|
||||
m_reactionNameMap.emplace(std::string(m_reactions[i]->id()), i);
|
||||
}
|
||||
|
||||
m_id.clear();
|
||||
for (const auto& r_ptr : m_reactions) {
|
||||
m_id += r_ptr->id();
|
||||
}
|
||||
}
|
||||
|
||||
bool ReactionSet::contains(const std::string_view& id) const {
|
||||
for (const auto& reaction : m_reactions) {
|
||||
if (reaction->id() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReactionSet::contains(const Reaction& reaction) const {
|
||||
for (const auto& r : m_reactions) {
|
||||
if (r->id() == reaction.id()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ReactionSet::clear() {
|
||||
m_reactions.clear();
|
||||
m_reactionNameMap.clear();
|
||||
}
|
||||
|
||||
bool ReactionSet::contains_species(const Species& species) const {
|
||||
for (const auto& reaction : m_reactions) {
|
||||
if (reaction->contains(species)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReactionSet::contains_reactant(const Species& species) const {
|
||||
for (const auto& r : m_reactions) {
|
||||
if (r->contains_reactant(species)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReactionSet::contains_product(const Species& species) const {
|
||||
for (const auto& r : m_reactions) {
|
||||
if (r->contains_product(species)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const Reaction& ReactionSet::operator[](const size_t index) const {
|
||||
if (index >= m_reactions.size()) {
|
||||
m_logger -> flush_log();
|
||||
throw std::out_of_range("Index" + std::to_string(index) + " out of range for ReactionSet of size " + std::to_string(m_reactions.size()) + ".");
|
||||
}
|
||||
return *m_reactions[index];
|
||||
}
|
||||
|
||||
const Reaction& ReactionSet::operator[](const std::string_view& id) const {
|
||||
if (auto it = m_reactionNameMap.find(std::string(id)); it != m_reactionNameMap.end()) {
|
||||
return *m_reactions[it->second];
|
||||
}
|
||||
m_logger -> flush_log();
|
||||
throw std::out_of_range("Species " + std::string(id) + " does not exist in ReactionSet.");
|
||||
}
|
||||
|
||||
bool ReactionSet::operator==(const ReactionSet& other) const {
|
||||
if (size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
return hash(0) == other.hash(0);
|
||||
}
|
||||
|
||||
bool ReactionSet::operator!=(const ReactionSet& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
uint64_t ReactionSet::hash(uint64_t seed) const {
|
||||
if (m_reactions.empty()) {
|
||||
return XXHash64::hash(nullptr, 0, seed);
|
||||
}
|
||||
std::vector<uint64_t> individualReactionHashes;
|
||||
individualReactionHashes.reserve(m_reactions.size());
|
||||
for (const auto& reaction : m_reactions) {
|
||||
individualReactionHashes.push_back(reaction->hash(seed));
|
||||
}
|
||||
|
||||
std::ranges::sort(individualReactionHashes);
|
||||
|
||||
const auto data = static_cast<const void*>(individualReactionHashes.data());
|
||||
const size_t sizeInBytes = individualReactionHashes.size() * sizeof(uint64_t);
|
||||
return XXHash64::hash(data, sizeInBytes, seed);
|
||||
}
|
||||
|
||||
std::unordered_set<Species> ReactionSet::getReactionSetSpecies() const {
|
||||
std::unordered_set<Species> species;
|
||||
for (const auto& reaction : m_reactions) {
|
||||
const auto reactionSpecies = reaction->all_species();
|
||||
species.insert(reactionSpecies.begin(), reactionSpecies.end());
|
||||
}
|
||||
return species;
|
||||
}
|
||||
|
||||
ReactionSet packReactionSet(const ReactionSet& reactionSet) {
|
||||
std::unordered_map<std::string, std::vector<ReaclibReaction>> groupedReaclibReactions;
|
||||
ReactionSet finalReactionSet;
|
||||
|
||||
for (const auto& reaction_ptr : reactionSet) {
|
||||
switch (reaction_ptr->type()) {
|
||||
case ReactionType::REACLIB: {
|
||||
const auto& reaclib_cast_reaction = static_cast<const ReaclibReaction&>(*reaction_ptr); // NOLINT(*-pro-type-static-cast-downcast)
|
||||
groupedReaclibReactions[std::string(reaclib_cast_reaction.peName())].push_back(reaclib_cast_reaction);
|
||||
break;
|
||||
}
|
||||
case ReactionType::LOGICAL_REACLIB: {
|
||||
// It doesn't make sense to pack an already-packed reaction.
|
||||
throw std::runtime_error("packReactionSet: Cannot pack a LogicalReaclibReaction.");
|
||||
}
|
||||
case ReactionType::WEAK: {
|
||||
finalReactionSet.add_reaction(*reaction_ptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, process the grouped REACLIB reactions
|
||||
for (const auto &reactionsGroup: groupedReaclibReactions | std::views::values) {
|
||||
if (reactionsGroup.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (reactionsGroup.size() == 1) {
|
||||
finalReactionSet.add_reaction(reactionsGroup.front());
|
||||
}
|
||||
else {
|
||||
const auto logicalReaction = std::make_unique<LogicalReaclibReaction>(reactionsGroup);
|
||||
finalReactionSet.add_reaction(logicalReaction->clone());
|
||||
}
|
||||
}
|
||||
|
||||
return finalReactionSet;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
@@ -302,11 +547,4 @@ namespace std {
|
||||
return s.hash(0);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<gridfire::reaction::LogicalReactionSet> {
|
||||
size_t operator()(const gridfire::reaction::LogicalReactionSet& s) const noexcept {
|
||||
return s.hash(0);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
94
src/lib/reaction/weak/weak.cpp
Normal file
94
src/lib/reaction/weak/weak.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "gridfire/reaction/weak/weak_rate_library.h"
|
||||
#include "gridfire/reaction/weak/weak.h"
|
||||
|
||||
#include "fourdst/composition/species.h"
|
||||
|
||||
#include <array>
|
||||
#include <ranges>
|
||||
#include <unordered_map>
|
||||
#include <expected>
|
||||
|
||||
#define GRIDFIRE_WEAK_REACTION_LIB_SENTINEL -60.0
|
||||
|
||||
namespace gridfire::rates::weak {
|
||||
WeakReactionMap::WeakReactionMap() {
|
||||
using namespace fourdst::atomic;
|
||||
|
||||
|
||||
for (const auto& weak_reaction_record : UNIFIED_WEAK_DATA) {
|
||||
Species species = az_to_species(weak_reaction_record.A, weak_reaction_record.Z);
|
||||
|
||||
if (weak_reaction_record.log_beta_minus > GRIDFIRE_WEAK_REACTION_LIB_SENTINEL) {
|
||||
m_weak_network[species].push_back(
|
||||
WeakReaction{
|
||||
WeakReactionType::BETA_MINUS_DECAY,
|
||||
weak_reaction_record.t9,
|
||||
weak_reaction_record.log_rhoye,
|
||||
weak_reaction_record.mu_e,
|
||||
weak_reaction_record.log_beta_minus,
|
||||
weak_reaction_record.log_antineutrino_loss_bd
|
||||
}
|
||||
);
|
||||
}
|
||||
if (weak_reaction_record.log_beta_plus > GRIDFIRE_WEAK_REACTION_LIB_SENTINEL) {
|
||||
m_weak_network[species].push_back(
|
||||
WeakReaction{
|
||||
WeakReactionType::BETA_PLUS_DECAY,
|
||||
weak_reaction_record.t9,
|
||||
weak_reaction_record.log_rhoye,
|
||||
weak_reaction_record.mu_e,
|
||||
weak_reaction_record.log_beta_plus,
|
||||
weak_reaction_record.log_neutrino_loss_ec
|
||||
}
|
||||
);
|
||||
}
|
||||
if (weak_reaction_record.log_electron_capture > GRIDFIRE_WEAK_REACTION_LIB_SENTINEL) {
|
||||
m_weak_network[species].push_back(
|
||||
WeakReaction{
|
||||
WeakReactionType::ELECTRON_CAPTURE,
|
||||
weak_reaction_record.t9,
|
||||
weak_reaction_record.log_rhoye,
|
||||
weak_reaction_record.mu_e,
|
||||
weak_reaction_record.log_electron_capture,
|
||||
weak_reaction_record.log_neutrino_loss_ec
|
||||
}
|
||||
);
|
||||
}
|
||||
if (weak_reaction_record.log_positron_capture > GRIDFIRE_WEAK_REACTION_LIB_SENTINEL) {
|
||||
m_weak_network[species].push_back(
|
||||
WeakReaction{
|
||||
WeakReactionType::POSITRON_CAPTURE,
|
||||
weak_reaction_record.t9,
|
||||
weak_reaction_record.log_rhoye,
|
||||
weak_reaction_record.mu_e,
|
||||
weak_reaction_record.log_positron_capture,
|
||||
weak_reaction_record.log_antineutrino_loss_bd
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<WeakReaction> WeakReactionMap::get_all_reactions() const {
|
||||
std::vector<WeakReaction> reactions;
|
||||
for (const auto &species_reactions: m_weak_network | std::views::values) {
|
||||
reactions.insert(reactions.end(), species_reactions.begin(), species_reactions.end());
|
||||
}
|
||||
return reactions;
|
||||
}
|
||||
|
||||
std::expected<std::vector<WeakReaction>, bool> WeakReactionMap::get_species_reactions(const fourdst::atomic::Species &species) const {
|
||||
if (m_weak_network.contains(species)) {
|
||||
return m_weak_network.at(species);
|
||||
}
|
||||
return std::unexpected(false);
|
||||
}
|
||||
|
||||
std::expected<std::vector<WeakReaction>, bool> WeakReactionMap::get_species_reactions(const std::string &species_name) const {
|
||||
fourdst::atomic::Species species = fourdst::atomic::species.at(species_name);
|
||||
if (m_weak_network.contains(species)) {
|
||||
return m_weak_network.at(species);
|
||||
}
|
||||
return std::unexpected(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user