fix(Reaction): resolved bug which prevented counting number of reactants and products properly
This bug was introduced when switching the internal tracking of products and reactants from a vector to a set. Initially we had done this to improve lookup performance. However, due to the uniquness of items in a set this broke counting methods. We have resolved this so that all old code will still work while maintaing the efficency gains by using an unordered map which stored species and counts. Further we have added countReactantOccurences and countProductOffurences methods to make this process more explicit and avalible to callers.
This commit is contained in:
0
src/include/gridfire/engine/types/jacobian.h
Normal file
0
src/include/gridfire/engine/types/jacobian.h
Normal file
@@ -217,6 +217,10 @@ namespace gridfire::reaction {
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] virtual std::unordered_set<fourdst::atomic::Species> product_species() const = 0;
|
[[nodiscard]] virtual std::unordered_set<fourdst::atomic::Species> product_species() const = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual size_t countReactantOccurrences(const fourdst::atomic::Species& species) const = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual size_t countProductOccurrences(const fourdst::atomic::Species& species) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Number of unique species involved in the reaction.
|
* @brief Number of unique species involved in the reaction.
|
||||||
* @return Count of distinct species across reactants and products.
|
* @return Count of distinct species across reactants and products.
|
||||||
@@ -525,10 +529,12 @@ namespace gridfire::reaction {
|
|||||||
if (!m_reactantsVec) {
|
if (!m_reactantsVec) {
|
||||||
m_reactantsVec.emplace(std::vector<fourdst::atomic::Species>());
|
m_reactantsVec.emplace(std::vector<fourdst::atomic::Species>());
|
||||||
m_reactantsVec->reserve(m_reactants.size());
|
m_reactantsVec->reserve(m_reactants.size());
|
||||||
for (const auto& reactant : m_reactants) {
|
for (const auto& [reactant, count] : m_reactants) {
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
m_reactantsVec->push_back(reactant);
|
m_reactantsVec->push_back(reactant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return m_reactantsVec.value();
|
return m_reactantsVec.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,10 +546,12 @@ namespace gridfire::reaction {
|
|||||||
if (!m_productsVec) {
|
if (!m_productsVec) {
|
||||||
m_productsVec.emplace(std::vector<fourdst::atomic::Species>());
|
m_productsVec.emplace(std::vector<fourdst::atomic::Species>());
|
||||||
m_productsVec->reserve(m_products.size());
|
m_productsVec->reserve(m_products.size());
|
||||||
for (const auto& product : m_products) {
|
for (const auto& [product, count] : m_products) {
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
m_productsVec->push_back(product);
|
m_productsVec->push_back(product);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return m_productsVec.value();
|
return m_productsVec.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,14 +595,24 @@ namespace gridfire::reaction {
|
|||||||
return os << "(ReaclibReaction:" << r.m_id << ")";
|
return os << "(ReaclibReaction:" << r.m_id << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t countReactantOccurrences(const fourdst::atomic::Species& species) const override {
|
||||||
|
if (!m_reactants.contains(species)) return 0;
|
||||||
|
return m_reactants.at(species);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t countProductOccurrences(const fourdst::atomic::Species& species) const override {
|
||||||
|
if (!m_products.contains(species)) return 0;
|
||||||
|
return m_products.at(species);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
|
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
|
||||||
std::string m_id; ///< Unique identifier for the reaction (e.g., "h1+h1=>h2+e+nu").
|
std::string m_id; ///< Unique identifier for the reaction (e.g., "h1+h1=>h2+e+nu").
|
||||||
std::string m_peName; ///< Name of the reaction in (projectile, ejectile) notation (e.g. "p(p,g)d").
|
std::string m_peName; ///< Name of the reaction in (projectile, ejectile) notation (e.g. "p(p,g)d").
|
||||||
int m_chapter; ///< Chapter number from the REACLIB database, defining the reaction structure.
|
int m_chapter; ///< Chapter number from the REACLIB database, defining the reaction structure.
|
||||||
double m_qValue = 0.0; ///< Q-value of the reaction in MeV.
|
double m_qValue = 0.0; ///< Q-value of the reaction in MeV.
|
||||||
std::set<fourdst::atomic::Species> m_reactants; ///< Reactants of the reaction.
|
std::unordered_map<fourdst::atomic::Species, size_t> m_reactants; ///< Reactants of the reaction.
|
||||||
std::set<fourdst::atomic::Species> m_products; ///< Products of the reaction.
|
std::unordered_map<fourdst::atomic::Species, size_t> m_products; ///< Products of the reaction.
|
||||||
|
|
||||||
mutable std::optional<std::vector<fourdst::atomic::Species>> m_reactantsVec;
|
mutable std::optional<std::vector<fourdst::atomic::Species>> m_reactantsVec;
|
||||||
mutable std::optional<std::vector<fourdst::atomic::Species>> m_productsVec;
|
mutable std::optional<std::vector<fourdst::atomic::Species>> m_productsVec;
|
||||||
@@ -836,6 +854,8 @@ namespace gridfire::reaction {
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] size_t size() const { return m_reactions.size(); }
|
[[nodiscard]] size_t size() const { return m_reactions.size(); }
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {return m_reactions.empty(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Removes all reactions from the set.
|
* @brief Removes all reactions from the set.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -400,6 +400,11 @@ namespace gridfire::rates::weak {
|
|||||||
*/
|
*/
|
||||||
double get_log_neutrino_loss_from_payload(const WeakRatePayload& payload) const;
|
double get_log_neutrino_loss_from_payload(const WeakRatePayload& payload) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] size_t countReactantOccurrences(const fourdst::atomic::Species &species) const override;
|
||||||
|
|
||||||
|
[[nodiscard]] size_t countProductOccurrences(const fourdst::atomic::Species &species) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief CppAD atomic that wraps weak-rate interpolation for AD evaluation.
|
* @brief CppAD atomic that wraps weak-rate interpolation for AD evaluation.
|
||||||
|
|||||||
0
src/lib/engine/types/jacobian.cpp
Normal file
0
src/lib/engine/types/jacobian.cpp
Normal file
@@ -40,11 +40,16 @@ namespace gridfire::reaction {
|
|||||||
m_peName(peName),
|
m_peName(peName),
|
||||||
m_chapter(chapter),
|
m_chapter(chapter),
|
||||||
m_qValue(qValue),
|
m_qValue(qValue),
|
||||||
m_reactants(reactants.begin(), reactants.end()),
|
|
||||||
m_products(products.begin(), products.end()),
|
|
||||||
m_sourceLabel(label),
|
m_sourceLabel(label),
|
||||||
m_rateCoefficients(sets),
|
m_rateCoefficients(sets),
|
||||||
m_reverse(reverse) {}
|
m_reverse(reverse) {
|
||||||
|
for (const auto& reactant : reactants) {
|
||||||
|
m_reactants[reactant]++;
|
||||||
|
}
|
||||||
|
for (const auto& product : products) {
|
||||||
|
m_products[product]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
double ReaclibReaction::calculate_rate(
|
double ReaclibReaction::calculate_rate(
|
||||||
const double T9,
|
const double T9,
|
||||||
@@ -107,11 +112,11 @@ namespace gridfire::reaction {
|
|||||||
|
|
||||||
|
|
||||||
bool ReaclibReaction::contains_reactant(const Species& species) const {
|
bool ReaclibReaction::contains_reactant(const Species& species) const {
|
||||||
return std::ranges::any_of(m_reactants, [&](const Species& r) { return r == species; });
|
return m_reactants.contains(species);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReaclibReaction::contains_product(const Species& species) const {
|
bool ReaclibReaction::contains_product(const Species& species) const {
|
||||||
return std::ranges::any_of(m_products, [&](const Species& p) { return p == species; });
|
return m_products.contains(species);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_set<Species> ReaclibReaction::all_species() const {
|
std::unordered_set<Species> ReaclibReaction::all_species() const {
|
||||||
@@ -123,7 +128,7 @@ namespace gridfire::reaction {
|
|||||||
|
|
||||||
std::unordered_set<Species> ReaclibReaction::reactant_species() const {
|
std::unordered_set<Species> ReaclibReaction::reactant_species() const {
|
||||||
std::unordered_set<Species> reactantsSet;
|
std::unordered_set<Species> reactantsSet;
|
||||||
for (const auto& reactant : m_reactants) {
|
for (const auto& reactant : m_reactants | std::views::keys) {
|
||||||
reactantsSet.insert(reactant);
|
reactantsSet.insert(reactant);
|
||||||
}
|
}
|
||||||
return reactantsSet;
|
return reactantsSet;
|
||||||
@@ -131,7 +136,7 @@ namespace gridfire::reaction {
|
|||||||
|
|
||||||
std::unordered_set<Species> ReaclibReaction::product_species() const {
|
std::unordered_set<Species> ReaclibReaction::product_species() const {
|
||||||
std::unordered_set<Species> productsSet;
|
std::unordered_set<Species> productsSet;
|
||||||
for (const auto& product : m_products) {
|
for (const auto& product : m_products | std::views::keys) {
|
||||||
productsSet.insert(product);
|
productsSet.insert(product);
|
||||||
}
|
}
|
||||||
return productsSet;
|
return productsSet;
|
||||||
@@ -139,14 +144,14 @@ namespace gridfire::reaction {
|
|||||||
|
|
||||||
int ReaclibReaction::stoichiometry(const Species& species) const {
|
int ReaclibReaction::stoichiometry(const Species& species) const {
|
||||||
int s = 0;
|
int s = 0;
|
||||||
for (const auto& reactant : m_reactants) {
|
for (const auto& [reactant, count] : m_reactants) {
|
||||||
if (reactant == species) {
|
if (reactant == species) {
|
||||||
s--;
|
s -= count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto& product : m_products) {
|
for (const auto& [product, count] : m_products) {
|
||||||
if (product == species) {
|
if (product == species) {
|
||||||
s++;
|
s += count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@@ -158,11 +163,8 @@ namespace gridfire::reaction {
|
|||||||
|
|
||||||
std::unordered_map<Species, int> ReaclibReaction::stoichiometry() const {
|
std::unordered_map<Species, int> ReaclibReaction::stoichiometry() const {
|
||||||
std::unordered_map<Species, int> stoichiometryMap;
|
std::unordered_map<Species, int> stoichiometryMap;
|
||||||
for (const auto& reactant : m_reactants) {
|
for (const auto& sp : all_species()) {
|
||||||
stoichiometryMap[reactant]--;
|
stoichiometryMap[sp] = stoichiometry(sp);
|
||||||
}
|
|
||||||
for (const auto& product : m_products) {
|
|
||||||
stoichiometryMap[product]++;
|
|
||||||
}
|
}
|
||||||
return stoichiometryMap;
|
return stoichiometryMap;
|
||||||
}
|
}
|
||||||
@@ -171,10 +173,10 @@ namespace gridfire::reaction {
|
|||||||
double reactantMass = 0.0;
|
double reactantMass = 0.0;
|
||||||
double productMass = 0.0;
|
double productMass = 0.0;
|
||||||
constexpr double AMU2MeV = 931.494893; // Conversion factor from atomic mass unit to MeV
|
constexpr double AMU2MeV = 931.494893; // Conversion factor from atomic mass unit to MeV
|
||||||
for (const auto& reactant : m_reactants) {
|
for (const auto& reactant : m_reactants | std::views::keys) {
|
||||||
reactantMass += reactant.mass();
|
reactantMass += reactant.mass();
|
||||||
}
|
}
|
||||||
for (const auto& product : m_products) {
|
for (const auto& product : m_products | std::views::keys) {
|
||||||
productMass += product.mass();
|
productMass += product.mass();
|
||||||
}
|
}
|
||||||
return (reactantMass - productMass) * AMU2MeV;
|
return (reactantMass - productMass) * AMU2MeV;
|
||||||
|
|||||||
@@ -490,6 +490,26 @@ namespace gridfire::rates::weak {
|
|||||||
return logNeutrinoLoss;
|
return logNeutrinoLoss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t WeakReaction::countReactantOccurrences(const fourdst::atomic::Species &species) const {
|
||||||
|
size_t count = 0;
|
||||||
|
for (const auto& reactant : m_reactants) {
|
||||||
|
if (reactant == species) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WeakReaction::countProductOccurrences(const fourdst::atomic::Species &species) const {
|
||||||
|
size_t count = 0;
|
||||||
|
for (const auto& product : m_products) {
|
||||||
|
if (product == species) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
// Note that the input vector tx is of size 2: [T9, log10(rho*Ye)]
|
// Note that the input vector tx is of size 2: [T9, log10(rho*Ye)]
|
||||||
bool WeakReaction::AtomicWeakRate::forward (
|
bool WeakReaction::AtomicWeakRate::forward (
|
||||||
const size_t p,
|
const size_t p,
|
||||||
|
|||||||
Reference in New Issue
Block a user