feat(GridFire): major design changes
Switching to an Engine + solver design. Also brought xxHash and Eigen in. Working on QSE and Culling.
This commit is contained in:
@@ -1,254 +0,0 @@
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include "fourdst/composition/atomicSpecies.h"
|
||||
|
||||
#include "cppad/cppad.hpp"
|
||||
|
||||
namespace gridfire::reaclib {
|
||||
/**
|
||||
* @struct RateFitSet
|
||||
* @brief Holds the seven fitting parameters for a single REACLIB rate set.
|
||||
* @details The thermonuclear reaction rate for a single set is calculated as:
|
||||
* rate = exp(a0 + a1/T9 + a2/T9^(-1/3) + a3*T9^(1/3) + a4*T9 + a5*T9^(5/3) + a6*ln(T9))
|
||||
* where T9 is the temperature in billions of Kelvin. The total rate for a
|
||||
* reaction is the sum of the rates from all its sets.
|
||||
*/
|
||||
struct RateFitSet {
|
||||
double a0, a1, a2, a3, a4, a5, a6;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct REACLIBReaction
|
||||
* @brief Represents a single nuclear reaction from the JINA REACLIB database.
|
||||
* @details This struct is designed to be constructed at compile time (constexpr) from
|
||||
* the data parsed by the Python generation script. It stores all necessary
|
||||
* information to identify a reaction and calculate its rate.
|
||||
*/
|
||||
class REACLIBReaction {
|
||||
private:
|
||||
std::string m_id; ///< Unique identifier for the reaction, generated by the Python script.
|
||||
std::string_view 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.
|
||||
std::vector<fourdst::atomic::Species> m_reactantNames; ///< Names of the reactant species involved in the reaction.
|
||||
std::vector<fourdst::atomic::Species> m_productNames; ///< Names of the product species produced by the reaction.
|
||||
double m_qValue; ///< Q-value of the reaction in MeV, representing the energy released or absorbed.
|
||||
std::string m_sourceLabel; ///< Source label for the rate data, indicating the origin of the rate coefficients (e.g., "wc12w", "st08").
|
||||
RateFitSet m_rateSets; ///< Fitting coefficients for the reaction rate, containing the seven parameters used in the rate calculation.
|
||||
bool m_reverse = false; ///< indicates if the reaction is reversed
|
||||
|
||||
friend bool operator==(const REACLIBReaction& lhs, const REACLIBReaction& rhs);
|
||||
friend bool operator!=(const REACLIBReaction& lhs, const REACLIBReaction& rhs);
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a REACLIBReaction object at compile time.
|
||||
* @param id A unique string identifier generated by the Python script.
|
||||
* @param chapter The REACLIB chapter number, defining the reaction structure.
|
||||
* @param reactants A vector of strings with the names of the reactant species.
|
||||
* @param products A vector of strings with the names of the product species.
|
||||
* @param qValue The Q-value of the reaction in MeV.
|
||||
* @param label The source label for the rate data (e.g., "wc12w", "st08").
|
||||
* @param sets A vector of RateFitSet, containing the fitting coefficients for the rate.
|
||||
* @param reverse A boolean indicating if the reaction is reversed (default is false).
|
||||
*/
|
||||
REACLIBReaction(
|
||||
std::string id,
|
||||
std::string_view peName,
|
||||
int chapter,
|
||||
std::vector<fourdst::atomic::Species> reactants,
|
||||
std::vector<fourdst::atomic::Species> products,
|
||||
double qValue,
|
||||
std::string label,
|
||||
RateFitSet sets,
|
||||
bool reverse = false)
|
||||
: m_id(std::move(id)),
|
||||
m_peName(peName),
|
||||
m_chapter(chapter),
|
||||
m_reactantNames(std::move(reactants)),
|
||||
m_productNames(std::move(products)),
|
||||
m_qValue(qValue),
|
||||
m_sourceLabel(std::move(label)),
|
||||
m_rateSets(sets),
|
||||
m_reverse(reverse) {}
|
||||
|
||||
template <typename GeneralScalarType>
|
||||
[[nodiscard]] GeneralScalarType calculate_rate(const GeneralScalarType T9) const {
|
||||
const GeneralScalarType T913 = CppAD::pow(T9, 1.0/3.0);
|
||||
const GeneralScalarType rateExponent = m_rateSets.a0 +
|
||||
m_rateSets.a1 / T9 +
|
||||
m_rateSets.a2 / T913 +
|
||||
m_rateSets.a3 * T913 +
|
||||
m_rateSets.a4 * T9 +
|
||||
m_rateSets.a5 * CppAD::pow(T9, 5.0/3.0) +
|
||||
m_rateSets.a6 * CppAD::log(T9);
|
||||
return CppAD::exp(rateExponent);
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::string& id() const { return m_id; }
|
||||
|
||||
[[nodiscard]] std::string_view peName() const { return m_peName; }
|
||||
|
||||
[[nodiscard]] int chapter() const { return m_chapter; }
|
||||
|
||||
[[nodiscard]] const std::vector<fourdst::atomic::Species>& reactants() const { return m_reactantNames; }
|
||||
|
||||
[[nodiscard]] const std::vector<fourdst::atomic::Species>& products() const { return m_productNames; }
|
||||
|
||||
[[nodiscard]] double qValue() const { return m_qValue; }
|
||||
|
||||
[[nodiscard]] std::string sourceLabel() const { return m_sourceLabel; }
|
||||
|
||||
[[nodiscard]] bool is_reverse() const { return m_reverse; }
|
||||
|
||||
[[nodiscard]] RateFitSet rateFits() const { return m_rateSets; }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const REACLIBReaction& reaction) {
|
||||
os << "REACLIBReaction(" << reaction.m_peName << ", "
|
||||
<< "Chapter: " << reaction.m_chapter << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
friend bool operator==(const REACLIBReaction& lhs, const REACLIBReaction& rhs);
|
||||
|
||||
friend bool operator!=(const REACLIBReaction& lhs, const REACLIBReaction& rhs);
|
||||
};
|
||||
|
||||
class REACLIBReactionSet {
|
||||
private:
|
||||
std::vector<REACLIBReaction> m_reactions;
|
||||
public:
|
||||
REACLIBReactionSet() = default;
|
||||
|
||||
explicit REACLIBReactionSet(std::vector<REACLIBReaction> r) : m_reactions(std::move(r)) {}
|
||||
|
||||
void add_reaction(const REACLIBReaction& reaction) {
|
||||
if (not contains(reaction.id())) {
|
||||
m_reactions.push_back(reaction);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_reaction(const REACLIBReaction& reaction) {
|
||||
if (contains(reaction.id())) {
|
||||
m_reactions.erase(std::remove_if(m_reactions.begin(), m_reactions.end(),
|
||||
[&reaction](const REACLIBReaction& r) { return r.id() == reaction.id(); }), m_reactions.end());
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] bool contains(const std::string& id) const {
|
||||
for (const auto& reaction : m_reactions) {
|
||||
if (reaction.id() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool contains(const REACLIBReaction& reaction) const {
|
||||
for (const auto& r : m_reactions) {
|
||||
if (r == reaction) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t size() const {
|
||||
return m_reactions.size();
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const REACLIBReactionSet& set) {
|
||||
os << "REACLIBReactionSet(";
|
||||
int reactionNo = 0;
|
||||
for (const auto& reaction : set.m_reactions) {
|
||||
reactionNo++;
|
||||
os << reaction.id();
|
||||
if (reactionNo < set.m_reactions.size()) {
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
os << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
void sort(double T9=1.0) {
|
||||
// Sort based on the evaluation of each reaction's rate function
|
||||
std::sort(m_reactions.begin(), m_reactions.end(),
|
||||
[T9](const REACLIBReaction& a, const REACLIBReaction& b) {
|
||||
return a.calculate_rate(T9) > b.calculate_rate(T9);
|
||||
});
|
||||
}
|
||||
|
||||
auto begin() {
|
||||
return m_reactions.begin();
|
||||
}
|
||||
|
||||
auto end() {
|
||||
return m_reactions.end();
|
||||
}
|
||||
|
||||
bool containsSpecies(const fourdst::atomic::Species &species) const {
|
||||
for (const auto& reaction : m_reactions) {
|
||||
if (std::ranges::find(reaction.reactants(), species) != reaction.reactants().end() ||
|
||||
std::ranges::find(reaction.products(), species) != reaction.products().end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] const REACLIBReaction& operator[](size_t index) const {
|
||||
if (index >= m_reactions.size()) {
|
||||
throw std::out_of_range("Index out of range in REACLIBReactionSet.");
|
||||
}
|
||||
return m_reactions[index];
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<REACLIBReaction> get_reactions() const {
|
||||
return m_reactions;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto begin() const {
|
||||
return m_reactions.cbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto end() const {
|
||||
return m_reactions.cend();
|
||||
}
|
||||
|
||||
};
|
||||
static std::unordered_map<std::string, REACLIBReaction> s_all_reaclib_reactions;
|
||||
static bool s_initialized = false;
|
||||
|
||||
inline bool operator==(const REACLIBReaction& lhs, const REACLIBReaction& rhs) {
|
||||
return lhs.m_id == rhs.m_id;
|
||||
}
|
||||
inline bool operator!=(const REACLIBReaction& lhs, const REACLIBReaction& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator==(const REACLIBReactionSet& lhs, const REACLIBReactionSet& rhs) {
|
||||
if (lhs.size() != rhs.size()) return false;
|
||||
for (const auto& reaction : lhs) {
|
||||
if (!rhs.contains(reaction)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!=(const REACLIBReactionSet& lhs, const REACLIBReactionSet& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<gridfire::reaclib::REACLIBReaction> {
|
||||
size_t operator()(const gridfire::reaclib::REACLIBReaction& r) const noexcept {
|
||||
return std::hash<std::string>()(r.id());
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
@@ -9,12 +9,15 @@
|
||||
#pragma once
|
||||
#include "fourdst/composition/atomicSpecies.h"
|
||||
#include "fourdst/composition/species.h"
|
||||
#include "reaclib.h"
|
||||
#include "gridfire/reaction/reaction.h"
|
||||
|
||||
namespace gridfire::reaclib {
|
||||
static std::unordered_map<std::string, reaction::REACLIBReaction> s_all_reaclib_reactions;
|
||||
static bool s_initialized = false;
|
||||
|
||||
|
||||
inline void initializeAllReaclibReactions() {
|
||||
using namespace reaction;
|
||||
if (s_initialized) return; // already initialized
|
||||
s_initialized = true;
|
||||
s_all_reaclib_reactions.clear();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
required_headers = [
|
||||
'gridfire/reaclib.h',
|
||||
'gridfire/reactions.h',
|
||||
]
|
||||
|
||||
@@ -14,7 +13,6 @@ reaclib_reactions_dep = declare_dependency(
|
||||
message('✅ GridFire reaclib_reactions dependency declared')
|
||||
|
||||
to_install_headers = [
|
||||
'include/gridfire/reaclib.h',
|
||||
'include/gridfire/reactions.h',
|
||||
]
|
||||
install_headers(to_install_headers, subdir: 'gridfire/gridfire')
|
||||
|
||||
Reference in New Issue
Block a user