This entailed a major rewrite of the composition handling from each engine and engine view along with the solver and primer. The intent here is to let Compositions be constructed from the same extensive property which the solver tracks internally. This addressed C0 discontinuity issues in the tracked molar abundances of species which were introduced by repeadidly swaping from molar abundance space to mass fraction space and back. This also allowed for a simplification of the primeNetwork method. Specifically the mass borrowing system was dramatically simplified as molar abundances are extensive.
392 lines
15 KiB
C++
392 lines
15 KiB
C++
#include <pybind11/pybind11.h>
|
|
#include <pybind11/stl.h> // Needed for vectors, maps, sets, strings
|
|
#include <pybind11/stl_bind.h> // Needed for binding std::vector, std::map etc. if needed directly
|
|
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#include "bindings.h"
|
|
|
|
#include "gridfire/reaction/reaction.h"
|
|
#include "gridfire/reaction/reaclib.h"
|
|
|
|
namespace py = pybind11;
|
|
|
|
|
|
void register_reaction_bindings(py::module &m) {
|
|
py::class_<gridfire::reaction::RateCoefficientSet>(m, "RateCoefficientSet")
|
|
.def(py::init<double, double, double, double, double, double, double>(),
|
|
py::arg("a0"), py::arg("a1"), py::arg("a2"), py::arg("a3"),
|
|
py::arg("a4"), py::arg("a5"), py::arg("a6"),
|
|
"Construct a RateCoefficientSet with the given parameters."
|
|
);
|
|
|
|
using fourdst::atomic::Species;
|
|
py::class_<gridfire::reaction::ReaclibReaction>(m, "ReaclibReaction")
|
|
.def(
|
|
py::init<
|
|
const std::string_view,
|
|
const std::string_view,
|
|
int,
|
|
const std::vector<Species>&,
|
|
const std::vector<Species>&,
|
|
double, std::string_view,
|
|
gridfire::reaction::RateCoefficientSet,
|
|
bool
|
|
>(),
|
|
py::arg("id"),
|
|
py::arg("peName"),
|
|
py::arg("chapter"),
|
|
py::arg("reactants"),
|
|
py::arg("products"),
|
|
py::arg("qValue"),
|
|
py::arg("label"),
|
|
py::arg("sets"),
|
|
py::arg("reverse") = false,
|
|
"Construct a Reaction with the given parameters."
|
|
)
|
|
.def(
|
|
"calculate_rate",
|
|
[](const gridfire::reaction::ReaclibReaction& self, const double T9, const double rho, const std::vector<double>& Y) -> double {
|
|
return self.calculate_rate(T9, rho, 0, {}, Y, {});
|
|
},
|
|
py::arg("T9"),
|
|
py::arg("rho"),
|
|
py::arg("Y"),
|
|
"Calculate the reaction rate at a given temperature T9 (in units of 10^9 K)."
|
|
)
|
|
.def(
|
|
"peName",
|
|
&gridfire::reaction::ReaclibReaction::peName,
|
|
"Get the reaction name in (projectile, ejectile) notation (e.g., 'p(p,g)d')."
|
|
)
|
|
.def(
|
|
"chapter",
|
|
&gridfire::reaction::ReaclibReaction::chapter,
|
|
"Get the REACLIB chapter number defining the reaction structure."
|
|
)
|
|
.def(
|
|
"sourceLabel",
|
|
&gridfire::reaction::ReaclibReaction::sourceLabel,
|
|
"Get the source label for the rate data (e.g., 'wc12w', 'st08')."
|
|
)
|
|
.def(
|
|
"rateCoefficients",
|
|
&gridfire::reaction::ReaclibReaction::rateCoefficients,
|
|
"get the set of rate coefficients."
|
|
)
|
|
.def(
|
|
"contains",
|
|
&gridfire::reaction::ReaclibReaction::contains,
|
|
py::arg("species"),
|
|
"Check if the reaction contains a specific species."
|
|
)
|
|
.def(
|
|
"contains_reactant",
|
|
&gridfire::reaction::ReaclibReaction::contains_reactant,
|
|
"Check if the reaction contains a specific reactant species."
|
|
)
|
|
.def(
|
|
"contains_product",
|
|
&gridfire::reaction::ReaclibReaction::contains_product,
|
|
"Check if the reaction contains a specific product species."
|
|
)
|
|
.def(
|
|
"all_species",
|
|
&gridfire::reaction::ReaclibReaction::all_species,
|
|
"Get all species involved in the reaction (both reactants and products) as a set."
|
|
)
|
|
.def(
|
|
"reactant_species",
|
|
&gridfire::reaction::ReaclibReaction::reactant_species,
|
|
"Get the reactant species of the reaction as a set."
|
|
)
|
|
.def(
|
|
"product_species",
|
|
&gridfire::reaction::ReaclibReaction::product_species,
|
|
"Get the product species of the reaction as a set."
|
|
)
|
|
.def(
|
|
"num_species",
|
|
&gridfire::reaction::ReaclibReaction::num_species,
|
|
"Count the number of species in the reaction."
|
|
)
|
|
.def(
|
|
"stoichiometry",
|
|
[](const gridfire::reaction::ReaclibReaction& self, const Species& species) -> int {
|
|
return self.stoichiometry(species);
|
|
},
|
|
py::arg("species"),
|
|
"Get the stoichiometry of the reaction as a map from species to their coefficients."
|
|
)
|
|
.def(
|
|
"stoichiometry",
|
|
[](const gridfire::reaction::ReaclibReaction& self) -> std::unordered_map<Species, int> {
|
|
return self.stoichiometry();
|
|
},
|
|
"Get the stoichiometry of the reaction as a map from species to their coefficients."
|
|
)
|
|
.def(
|
|
"id",
|
|
&gridfire::reaction::ReaclibReaction::id,
|
|
"Get the unique identifier of the reaction."
|
|
)
|
|
.def(
|
|
"qValue",
|
|
&gridfire::reaction::ReaclibReaction::qValue,
|
|
"Get the Q-value of the reaction in MeV."
|
|
)
|
|
.def(
|
|
"reactants",
|
|
&gridfire::reaction::ReaclibReaction::reactants,
|
|
"Get a list of reactant species in the reaction."
|
|
)
|
|
.def(
|
|
"products",
|
|
&gridfire::reaction::ReaclibReaction::products,
|
|
"Get a list of product species in the reaction."
|
|
)
|
|
.def(
|
|
"is_reverse",
|
|
&gridfire::reaction::ReaclibReaction::is_reverse,
|
|
"Check if this is a reverse reaction rate."
|
|
)
|
|
.def(
|
|
"excess_energy",
|
|
&gridfire::reaction::ReaclibReaction::excess_energy,
|
|
"Calculate the excess energy from the mass difference of reactants and products."
|
|
)
|
|
.def(
|
|
"__eq__",
|
|
&gridfire::reaction::ReaclibReaction::operator==,
|
|
"Equality operator for reactions based on their IDs."
|
|
)
|
|
.def(
|
|
"__neq__",
|
|
&gridfire::reaction::ReaclibReaction::operator!=,
|
|
"Inequality operator for reactions based on their IDs."
|
|
)
|
|
.def(
|
|
"hash",
|
|
&gridfire::reaction::ReaclibReaction::hash,
|
|
py::arg("seed") = 0,
|
|
"Compute a hash for the reaction based on its ID."
|
|
)
|
|
.def(
|
|
"__repr__",
|
|
[](const gridfire::reaction::ReaclibReaction& self) {
|
|
std::stringstream ss;
|
|
ss << self; // Use the existing operator<< for Reaction
|
|
return ss.str();
|
|
}
|
|
);
|
|
|
|
py::class_<gridfire::reaction::LogicalReaclibReaction, gridfire::reaction::ReaclibReaction>(m, "LogicalReaclibReaction")
|
|
.def(
|
|
py::init<const std::vector<gridfire::reaction::ReaclibReaction>>(),
|
|
py::arg("reactions"),
|
|
"Construct a LogicalReaclibReaction from a vector of ReaclibReaction objects."
|
|
)
|
|
.def(
|
|
py::init<const std::vector<gridfire::reaction::ReaclibReaction>, bool>(),
|
|
py::arg("reactions"),
|
|
py::arg("is_reverse"),
|
|
"Construct a LogicalReaclibReaction from a vector of ReaclibReaction objects."
|
|
)
|
|
.def(
|
|
"add_reaction",
|
|
&gridfire::reaction::LogicalReaclibReaction::add_reaction,
|
|
py::arg("reaction"),
|
|
"Add another Reaction source to this logical reaction."
|
|
)
|
|
.def(
|
|
"size",
|
|
&gridfire::reaction::LogicalReaclibReaction::size,
|
|
"Get the number of source rates contributing to this logical reaction."
|
|
)
|
|
.def(
|
|
"__len__",
|
|
&gridfire::reaction::LogicalReaclibReaction::size,
|
|
"Overload len() to return the number of source rates."
|
|
)
|
|
.def(
|
|
"sources",
|
|
&gridfire::reaction::LogicalReaclibReaction::sources,
|
|
"Get the list of source labels for the aggregated rates."
|
|
)
|
|
.def(
|
|
"calculate_rate",
|
|
[](
|
|
const gridfire::reaction::LogicalReaclibReaction& self,
|
|
const double T9,
|
|
const double rho,
|
|
const double Ye,
|
|
const double mue,
|
|
const std::vector<double>& Y,
|
|
const std::unordered_map<size_t, Species>& index_to_species_map
|
|
) -> double {
|
|
return self.calculate_rate(T9, rho, Ye, mue, Y, index_to_species_map);
|
|
},
|
|
py::arg("T9"),
|
|
py::arg("rho"),
|
|
py::arg("Ye"),
|
|
py::arg("mue"),
|
|
py::arg("Y"),
|
|
py::arg("index_to_species_map"),
|
|
"Calculate the reaction rate at a given temperature T9 (in units of 10^9 K). Note that for a reaclib reaction only T9 is actually used, all other parameters are there for interface compatibility."
|
|
)
|
|
.def(
|
|
"calculate_forward_rate_log_derivative",
|
|
&gridfire::reaction::LogicalReaclibReaction::calculate_log_rate_partial_deriv_wrt_T9,
|
|
py::arg("T9"),
|
|
py::arg("rho"),
|
|
py::arg("Ye"),
|
|
py::arg("mue"),
|
|
py::arg("Composition"),
|
|
"Calculate the forward rate log derivative at a given temperature T9 (in units of 10^9 K)."
|
|
);
|
|
|
|
py::class_<gridfire::reaction::ReactionSet>(m, "ReactionSet")
|
|
.def(
|
|
py::init<const std::vector<gridfire::reaction::Reaction*>>(),
|
|
py::arg("reactions"),
|
|
py::keep_alive<1, 2>(), // Keep arg 2 (reactions) alive as long as arg 1 (self) is alive. This helps mitigate use-after-free errors
|
|
"Construct a LogicalReactionSet from a vector of LogicalReaclibReaction objects."
|
|
)
|
|
.def_static(
|
|
"from_clones",
|
|
[](const std::vector<gridfire::reaction::Reaction*>& py_reactions) {
|
|
std::vector<std::unique_ptr<gridfire::reaction::Reaction>> cpp_reactions;
|
|
cpp_reactions.reserve(py_reactions.size());
|
|
for (const auto& reaction : py_reactions) {
|
|
cpp_reactions.emplace_back(reaction->clone());
|
|
}
|
|
return std::make_unique<gridfire::reaction::ReactionSet>(std::move(cpp_reactions));
|
|
},
|
|
py::arg("reactions"),
|
|
"Create a ReactionSet that takes ownership of the reactions by cloning the input reactions."
|
|
)
|
|
.def(
|
|
py::init<>(),
|
|
"Default constructor for an empty LogicalReactionSet."
|
|
)
|
|
.def(
|
|
py::init<const gridfire::reaction::ReactionSet&>(),
|
|
py::arg("other"),
|
|
"Copy constructor for LogicalReactionSet."
|
|
)
|
|
.def(
|
|
"add_reaction",
|
|
py::overload_cast<const gridfire::reaction::Reaction&>(&gridfire::reaction::ReactionSet::add_reaction),
|
|
py::arg("reaction"),
|
|
"Add a LogicalReaclibReaction to the set."
|
|
)
|
|
.def(
|
|
"remove_reaction",
|
|
&gridfire::reaction::ReactionSet::remove_reaction,
|
|
py::arg("reaction"),
|
|
"Remove a LogicalReaclibReaction from the set."
|
|
)
|
|
.def(
|
|
"contains",
|
|
py::overload_cast<const std::string_view&>(&gridfire::reaction::ReactionSet::contains, py::const_),
|
|
py::arg("id"),
|
|
"Check if the set contains a specific LogicalReaclibReaction."
|
|
)
|
|
.def(
|
|
"contains",
|
|
py::overload_cast<const gridfire::reaction::Reaction&>(&gridfire::reaction::ReactionSet::contains, py::const_),
|
|
py::arg("reaction"),
|
|
"Check if the set contains a specific Reaction."
|
|
)
|
|
.def(
|
|
"size",
|
|
&gridfire::reaction::ReactionSet::size,
|
|
"Get the number of LogicalReactions in the set."
|
|
)
|
|
.def(
|
|
"__len__", &gridfire::reaction::ReactionSet::size,
|
|
"Overload len() to return the number of LogicalReactions."
|
|
)
|
|
.def(
|
|
"clear",
|
|
&gridfire::reaction::ReactionSet::clear,
|
|
"Remove all LogicalReactions from the set."
|
|
)
|
|
.def("contains_species",
|
|
&gridfire::reaction::ReactionSet::contains_species,
|
|
py::arg("species"),
|
|
"Check if any reaction in the set involves the given species."
|
|
)
|
|
.def(
|
|
"contains_reactant",
|
|
&gridfire::reaction::ReactionSet::contains_reactant,
|
|
py::arg("species"),
|
|
"Check if any reaction in the set has the species as a reactant."
|
|
)
|
|
.def(
|
|
"contains_product",
|
|
&gridfire::reaction::ReactionSet::contains_product,
|
|
py::arg("species"),
|
|
"Check if any reaction in the set has the species as a product."
|
|
)
|
|
.def(
|
|
"__getitem__",
|
|
py::overload_cast<size_t>(&gridfire::reaction::ReactionSet::operator[], py::const_),
|
|
py::return_value_policy::reference,
|
|
py::arg("index"),
|
|
"Get a LogicalReaclibReaction by index."
|
|
)
|
|
.def(
|
|
"__getitem___",
|
|
py::overload_cast<const std::string_view&>(&gridfire::reaction::ReactionSet::operator[], py::const_),
|
|
py::return_value_policy::reference,
|
|
py::arg("id"),
|
|
"Get a LogicalReaclibReaction by its ID."
|
|
)
|
|
.def(
|
|
"__eq__",
|
|
&gridfire::reaction::ReactionSet::operator==,
|
|
py::arg("LogicalReactionSet"),
|
|
"Equality operator for LogicalReactionSets based on their contents."
|
|
)
|
|
.def(
|
|
"__ne__",
|
|
&gridfire::reaction::ReactionSet::operator!=,
|
|
py::arg("LogicalReactionSet"),
|
|
"Inequality operator for LogicalReactionSets based on their contents."
|
|
)
|
|
.def(
|
|
"hash",
|
|
&gridfire::reaction::ReactionSet::hash,
|
|
py::arg("seed") = 0,
|
|
"Compute a hash for the LogicalReactionSet based on its contents."
|
|
)
|
|
.def(
|
|
"__repr__",
|
|
[](const gridfire::reaction::ReactionSet& self) {
|
|
std::stringstream ss;
|
|
ss << self;
|
|
return ss.str();
|
|
}
|
|
)
|
|
.def(
|
|
"getReactionSetSpecies",
|
|
&gridfire::reaction::ReactionSet::getReactionSetSpecies,
|
|
"Get all species involved in the reactions of the set as a set of Species objects."
|
|
);
|
|
|
|
m.def(
|
|
"packReactionSet",
|
|
&gridfire::reaction::packReactionSet,
|
|
py::arg("reactionSet"),
|
|
"Convert a ReactionSet to a LogicalReactionSet by aggregating reactions with the same peName."
|
|
);
|
|
|
|
m.def(
|
|
"get_all_reactions",
|
|
&gridfire::reaclib::get_all_reaclib_reactions,
|
|
"Get all reactions from the REACLIB database."
|
|
);
|
|
}
|