GridFire 0.0.1a General Purpose Nuclear Network

Loading...
Searching...
No Matches
reaction.cpp
Go to the documentation of this file.
1#include "gridfire/reaction/reaction.h"
2
3#include<string_view>
4#include<string>
5#include<vector>
6#include<unordered_set>
7#include<algorithm>
8#include <ranges>
9
10#include "quill/LogMacros.h"
11
12#include "fourdst/composition/atomicSpecies.h"
13
14#include "xxhash64.h"
15
16 namespace gridfire::reaction {
17 using namespace fourdst::atomic;
18
19 Reaction::Reaction(
20 const std::string_view id,
21 const std::string_view peName,
22 const int chapter,
23 const std::vector<Species>& reactants,
24 const std::vector<Species>& products,
25 const double qValue,
26 const std::string_view label,
27 const RateCoefficientSet& sets,
28 const bool reverse) :
29 m_id(id),
30 m_peName(peName),
31 m_chapter(chapter),
32 m_qValue(qValue),
33 m_reactants(reactants),
34 m_products(products),
35 m_sourceLabel(label),
36 m_rateCoefficients(sets),
37 m_reverse(reverse) {}
38
39 double Reaction::calculate_rate(const double T9) const {
40 return calculate_rate<double>(T9);
41 }
42
43 CppAD::AD<double> Reaction::calculate_rate(const CppAD::AD<double> T9) const {
44 return calculate_rate<CppAD::AD<double>>(T9);
45 }
46
47 double Reaction::calculate_forward_rate_log_derivative(const double T9) const {
48 constexpr double r_p13 = 1.0 / 3.0;
49 constexpr double r_p53 = 5.0 / 3.0;
50 constexpr double r_p23 = 2.0 / 3.0;
51 constexpr double r_p43 = 4.0 / 3.0;
52
53 const double T9_m1 = 1.0 / T9;
54 const double T9_m23 = std::pow(T9, -r_p23);
55 const double T9_m43 = std::pow(T9, -r_p43);
56
57 const double d_log_k_fwd_dT9 =
58 -m_rateCoefficients.a1 * T9_m1 * T9_m1
59 - r_p13 * m_rateCoefficients.a2 * T9_m43
60 + r_p13 * m_rateCoefficients.a3 * T9_m23
61 + m_rateCoefficients.a4
62 + r_p53 * m_rateCoefficients.a5 * std::pow(T9, r_p23)
63 + m_rateCoefficients.a6 * T9_m1;
64
65 return d_log_k_fwd_dT9; // Return the derivative of the log rate with respect to T9
66 }
67
68 bool Reaction::contains(const Species &species) const {
69 return contains_reactant(species) || contains_product(species);
70 }
71
72
73 bool Reaction::contains_reactant(const Species& species) const {
74 for (const auto& reactant : m_reactants) {
75 if (reactant == species) {
76 return true;
77 }
78 }
79 return false;
80 }
81
82 bool Reaction::contains_product(const Species& species) const {
83 for (const auto& product : m_products) {
84 if (product == species) {
85 return true;
86 }
87 }
88 return false;
89 }
90
91 std::unordered_set<Species> Reaction::all_species() const {
92 auto rs = reactant_species();
93 auto ps = product_species();
94 rs.insert(ps.begin(), ps.end());
95 return rs;
96 }
97
98 std::unordered_set<Species> Reaction::reactant_species() const {
99 std::unordered_set<Species> reactantsSet;
100 for (const auto& reactant : m_reactants) {
101 reactantsSet.insert(reactant);
102 }
103 return reactantsSet;
104 }
105
106 std::unordered_set<Species> Reaction::product_species() const {
107 std::unordered_set<Species> productsSet;
108 for (const auto& product : m_products) {
109 productsSet.insert(product);
110 }
111 return productsSet;
112 }
113
114 int Reaction::stoichiometry(const Species& species) const {
115 int s = 0;
116 for (const auto& reactant : m_reactants) {
117 if (reactant == species) {
118 s--;
119 }
120 }
121 for (const auto& product : m_products) {
122 if (product == species) {
123 s++;
124 }
125 }
126 return s;
127 }
128
129 size_t Reaction::num_species() const {
130 return all_species().size();
131 }
132
133 std::unordered_map<Species, int> Reaction::stoichiometry() const {
134 std::unordered_map<Species, int> stoichiometryMap;
135 for (const auto& reactant : m_reactants) {
136 stoichiometryMap[reactant]--;
137 }
138 for (const auto& product : m_products) {
139 stoichiometryMap[product]++;
140 }
141 return stoichiometryMap;
142 }
143
144 double Reaction::excess_energy() const {
145 double reactantMass = 0.0;
146 double productMass = 0.0;
147 constexpr double AMU2MeV = 931.494893; // Conversion factor from atomic mass unit to MeV
148 for (const auto& reactant : m_reactants) {
149 reactantMass += reactant.mass();
150 }
151 for (const auto& product : m_products) {
152 productMass += product.mass();
153 }
154 return (reactantMass - productMass) * AMU2MeV;
155 }
156
157 uint64_t Reaction::hash(const uint64_t seed) const {
158 return XXHash64::hash(m_id.data(), m_id.size(), seed);
159 }
160
161
162
163 LogicalReaction::LogicalReaction(const std::vector<Reaction>& reactants) :
164 Reaction(reactants.front().peName(),
165 reactants.front().peName(),
166 reactants.front().chapter(),
167 reactants.front().reactants(),
168 reactants.front().products(),
169 reactants.front().qValue(),
170 reactants.front().sourceLabel(),
171 reactants.front().rateCoefficients(),
172 reactants.front().is_reverse()) {
173
174 m_sources.reserve(reactants.size());
175 m_rates.reserve(reactants.size());
176 for (const auto& reaction : reactants) {
177 if (std::abs(std::abs(reaction.qValue()) - std::abs(m_qValue)) > 1e-6) {
178 LOG_ERROR(
179 m_logger,
180 "LogicalReaction constructed with reactions having different Q-values. Expected {} got {}.",
181 m_qValue,
182 reaction.qValue()
183 );
184 m_logger -> flush_log();
185 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)) + ").");
186 }
187 m_sources.push_back(std::string(reaction.sourceLabel()));
188 m_rates.push_back(reaction.rateCoefficients());
189 }
190 }
191
192 void LogicalReaction::add_reaction(const Reaction& reaction) {
193 if (reaction.peName() != m_id) {
194 LOG_ERROR(m_logger, "Cannot add reaction with different peName to LogicalReaction. Expected {} got {}.", m_id, reaction.peName());
195 m_logger -> flush_log();
196 throw std::runtime_error("Cannot add reaction with different peName to LogicalReaction. Expected " + std::string(m_id) + " got " + std::string(reaction.peName()) + ".");
197 }
198 for (const auto& source : m_sources) {
199 if (source == reaction.sourceLabel()) {
200 LOG_ERROR(m_logger, "Cannot add reaction with duplicate source label {} to LogicalReaction.", reaction.sourceLabel());
201 m_logger -> flush_log();
202 throw std::runtime_error("Cannot add reaction with duplicate source label " + std::string(reaction.sourceLabel()) + " to LogicalReaction.");
203 }
204 }
205 if (std::abs(reaction.qValue() - m_qValue) > 1e-6) {
206 LOG_ERROR(m_logger, "LogicalReaction constructed with reactions having different Q-values. Expected {} got {}.", m_qValue, reaction.qValue());
207 m_logger -> flush_log();
208 throw std::runtime_error("LogicalReaction constructed with reactions having different Q-values. Expected " + std::to_string(m_qValue) + " got " + std::to_string(reaction.qValue()) + ".");
209 }
210 m_sources.push_back(std::string(reaction.sourceLabel()));
211 m_rates.push_back(reaction.rateCoefficients());
212 }
213
214 double LogicalReaction::calculate_rate(const double T9) const {
215 return calculate_rate<double>(T9);
216 }
217
218 double LogicalReaction::calculate_forward_rate_log_derivative(const double T9) const {
219 constexpr double r_p13 = 1.0 / 3.0;
220 constexpr double r_p53 = 5.0 / 3.0;
221 constexpr double r_p23 = 2.0 / 3.0;
222 constexpr double r_p43 = 4.0 / 3.0;
223
224 double totalRate = 0.0;
225 double totalRateDerivative = 0.0;
226
227
228 const double T9_m1 = 1.0 / T9;
229 const double T913 = std::pow(T9, r_p13);
230 const double T953 = std::pow(T9, r_p53);
231 const double logT9 = std::log(T9);
232
233 const double T9_m1_sq = T9_m1 * T9_m1;
234 const double T9_m23 = std::pow(T9, -r_p23);
235 const double T9_m43 = std::pow(T9, -r_p43);
236 const double T9_p23 = std::pow(T9, r_p23);
237
238
239 for (const auto& coeffs : m_rates) {
240 const double exponent = coeffs.a0 +
241 coeffs.a1 * T9_m1 +
242 coeffs.a2 / T913 +
243 coeffs.a3 * T913 +
244 coeffs.a4 * T9 +
245 coeffs.a5 * T953 +
246 coeffs.a6 * logT9;
247 const double individualRate = std::exp(exponent);
248
249 const double d_exponent_T9 =
250 -coeffs.a1 * T9_m1_sq
251 - r_p13 * coeffs.a2 * T9_m43
252 + r_p13 * coeffs.a3 * T9_m23
253 + coeffs.a4
254 + r_p53 * coeffs.a5 * T9_p23
255 + coeffs.a6 * T9_m1;
256
257 const double individualRateDerivative = individualRate * d_exponent_T9;
258 totalRate += individualRate;
259 totalRateDerivative += individualRateDerivative;
260 }
261
262 if (totalRate == 0.0) {
263 return 0.0; // Avoid division by zero
264 }
265
266 return totalRateDerivative / totalRate;
267 }
268
269 CppAD::AD<double> LogicalReaction::calculate_rate(const CppAD::AD<double> T9) const {
270 return calculate_rate<CppAD::AD<double>>(T9);
271 }
272
273 LogicalReactionSet packReactionSetToLogicalReactionSet(const ReactionSet& reactionSet) {
274 std::unordered_map<std::string_view, std::vector<Reaction>> groupedReactions;
275
276 for (const auto& reaction: reactionSet) {
277 groupedReactions[reaction.peName()].push_back(reaction);
278 }
279
280 std::vector<LogicalReaction> reactions;
281 reactions.reserve(groupedReactions.size());
282
283 for (const auto &reactionsGroup: groupedReactions | std::views::values) {
284 LogicalReaction logicalReaction(reactionsGroup);
285 reactions.push_back(logicalReaction);
286 }
287 return LogicalReactionSet(std::move(reactions));
288 }
289}
290
291 namespace std {
292 template<>
293 struct hash<gridfire::reaction::Reaction> {
294 size_t operator()(const gridfire::reaction::Reaction& r) const noexcept {
295 return r.hash(0);
296 }
297 };
298
299 template<>
300 struct hash<gridfire::reaction::ReactionSet> {
301 size_t operator()(const gridfire::reaction::ReactionSet& s) const noexcept {
302 return s.hash(0);
303 }
304 };
305
306 template<>
307 struct hash<gridfire::reaction::LogicalReactionSet> {
308 size_t operator()(const gridfire::reaction::LogicalReactionSet& s) const noexcept {
309 return s.hash(0);
310 }
311 };
312} // namespace std
gridfire::reaction::LogicalReaction
Represents a "logical" reaction that aggregates rates from multiple sources.
Definition reaction.h:310
gridfire::reaction::LogicalReaction::add_reaction
void add_reaction(const Reaction &reaction)
Adds another Reaction source to this logical reaction.
Definition reaction.cpp:192
gridfire::reaction::LogicalReaction::calculate_rate
double calculate_rate(const double T9) const override
Calculates the total reaction rate by summing all source rates.
Definition reaction.cpp:214
gridfire::reaction::LogicalReaction::LogicalReaction
LogicalReaction(const std::vector< Reaction > &reactions)
Constructs a LogicalReaction from a vector of Reaction objects.
Definition reaction.cpp:163
gridfire::reaction::LogicalReaction::m_sources
std::vector< std::string > m_sources
List of source labels.
Definition reaction.h:372
gridfire::reaction::LogicalReaction::m_rates
std::vector< RateCoefficientSet > m_rates
List of rate coefficient sets from each source.
Definition reaction.h:373
gridfire::reaction::LogicalReaction::calculate_forward_rate_log_derivative
virtual double calculate_forward_rate_log_derivative(const double T9) const override
Definition reaction.cpp:218
gridfire::reaction::Reaction
Represents a single nuclear reaction from a specific data source.
Definition reaction.h:72
gridfire::reaction::Reaction::m_sourceLabel
std::string m_sourceLabel
Source label for the rate data (e.g., "wc12w", "st08").
Definition reaction.h:270
gridfire::reaction::Reaction::product_species
std::unordered_set< fourdst::atomic::Species > product_species() const
Gets a set of all unique product species.
Definition reaction.cpp:106
gridfire::reaction::Reaction::contains_product
bool contains_product(const fourdst::atomic::Species &species) const
Checks if the reaction involves a given species as a product.
Definition reaction.cpp:82
gridfire::reaction::Reaction::id
std::string_view id() const
Gets the unique identifier of the reaction.
Definition reaction.h:204
gridfire::reaction::Reaction::m_reverse
bool m_reverse
Flag indicating if this is a reverse reaction rate.
Definition reaction.h:272
gridfire::reaction::Reaction::reactants
const std::vector< fourdst::atomic::Species > & reactants() const
Gets the vector of reactant species.
Definition reaction.h:216
gridfire::reaction::Reaction::m_chapter
int m_chapter
Chapter number from the REACLIB database, defining the reaction structure.
Definition reaction.h:266
gridfire::reaction::Reaction::num_species
size_t num_species() const
Gets the number of unique species involved in the reaction.
Definition reaction.cpp:129
gridfire::reaction::Reaction::calculate_forward_rate_log_derivative
virtual double calculate_forward_rate_log_derivative(const double T9) const
Definition reaction.cpp:47
gridfire::reaction::Reaction::sourceLabel
std::string_view sourceLabel() const
Gets the source label for the rate data.
Definition reaction.h:134
gridfire::reaction::Reaction::m_products
std::vector< fourdst::atomic::Species > m_products
Products of the reaction.
Definition reaction.h:269
gridfire::reaction::Reaction::m_qValue
double m_qValue
Q-value of the reaction in MeV.
Definition reaction.h:267
gridfire::reaction::Reaction::m_id
std::string m_id
Unique identifier for the reaction (e.g., "h1+h1=>h2+e+nu").
Definition reaction.h:264
gridfire::reaction::Reaction::chapter
int chapter() const
Gets the REACLIB chapter number.
Definition reaction.h:128
gridfire::reaction::Reaction::m_peName
std::string m_peName
Name of the reaction in (projectile, ejectile) notation (e.g. "p(p,g)d").
Definition reaction.h:265
gridfire::reaction::Reaction::products
const std::vector< fourdst::atomic::Species > & products() const
Gets the vector of product species.
Definition reaction.h:222
gridfire::reaction::Reaction::m_logger
quill::Logger * m_logger
Definition reaction.h:263
gridfire::reaction::Reaction::peName
virtual std::string_view peName() const
Gets the reaction name in (projectile, ejectile) notation.
Definition reaction.h:122
gridfire::reaction::Reaction::all_species
std::unordered_set< fourdst::atomic::Species > all_species() const
Gets a set of all unique species involved in the reaction.
Definition reaction.cpp:91
gridfire::reaction::Reaction::Reaction
Reaction(const std::string_view id, const std::string_view peName, const int chapter, const std::vector< fourdst::atomic::Species > &reactants, const std::vector< fourdst::atomic::Species > &products, const double qValue, const std::string_view label, const RateCoefficientSet &sets, const bool reverse=false)
Constructs a Reaction object.
Definition reaction.cpp:19
gridfire::reaction::Reaction::reactant_species
std::unordered_set< fourdst::atomic::Species > reactant_species() const
Gets a set of all unique reactant species.
Definition reaction.cpp:98
gridfire::reaction::Reaction::rateCoefficients
const RateCoefficientSet & rateCoefficients() const
Gets the set of rate coefficients.
Definition reaction.h:140
gridfire::reaction::Reaction::m_reactants
std::vector< fourdst::atomic::Species > m_reactants
Reactants of the reaction.
Definition reaction.h:268
gridfire::reaction::Reaction::excess_energy
double excess_energy() const
Calculates the excess energy from the mass difference of reactants and products.
Definition reaction.cpp:144
gridfire::reaction::Reaction::m_rateCoefficients
RateCoefficientSet m_rateCoefficients
The seven rate coefficients.
Definition reaction.h:271
gridfire::reaction::Reaction::is_reverse
bool is_reverse() const
Checks if this is a reverse reaction rate.
Definition reaction.h:228
gridfire::reaction::Reaction::contains
bool contains(const fourdst::atomic::Species &species) const
Checks if the reaction involves a given species as a reactant or product.
Definition reaction.cpp:68
gridfire::reaction::Reaction::contains_reactant
bool contains_reactant(const fourdst::atomic::Species &species) const
Checks if the reaction involves a given species as a reactant.
Definition reaction.cpp:73
gridfire::reaction::Reaction::qValue
double qValue() const
Gets the Q-value of the reaction.
Definition reaction.h:210
gridfire::reaction::Reaction::stoichiometry
std::unordered_map< fourdst::atomic::Species, int > stoichiometry() const
Gets a map of all species to their stoichiometric coefficients.
Definition reaction.cpp:133
gridfire::reaction::Reaction::calculate_rate
virtual double calculate_rate(const double T9) const
Calculates the reaction rate for a given temperature.
Definition reaction.cpp:39
gridfire::reaction::Reaction::hash
uint64_t hash(uint64_t seed=0) const
Computes a hash for the reaction based on its ID.
Definition reaction.cpp:157
gridfire::reaction
Definition reaction.h:25
gridfire::reaction::LogicalReactionSet
TemplatedReactionSet< LogicalReaction > LogicalReactionSet
A set of logical reactions.
Definition reaction.h:563
gridfire::reaction::packReactionSetToLogicalReactionSet
LogicalReactionSet packReactionSetToLogicalReactionSet(const ReactionSet &reactionSet)
Definition reaction.cpp:273
gridfire::reaction::ReactionSet
TemplatedReactionSet< Reaction > ReactionSet
A set of reactions, typically from a single source like REACLIB.
Definition reaction.h:562
gridfire
Definition engine_abstract.h:31
std
STL namespace.
reaction.h
Defines classes for representing and managing nuclear reactions.
gridfire::reaction::RateCoefficientSet
Holds the seven coefficients for the REACLIB rate equation.
Definition reaction.h:33
std::hash< gridfire::reaction::LogicalReactionSet >::operator()
size_t operator()(const gridfire::reaction::LogicalReactionSet &s) const noexcept
Definition reaction.cpp:308
std::hash< gridfire::reaction::Reaction >::operator()
size_t operator()(const gridfire::reaction::Reaction &r) const noexcept
Definition reaction.cpp:294
std::hash< gridfire::reaction::ReactionSet >::operator()
size_t operator()(const gridfire::reaction::ReactionSet &s) const noexcept
Definition reaction.cpp:301