feat(python): Repaired python bindings

Python bindings have now been brought back up to feature pairity with
C++. Further, stubs have been added for all python features so that code
completion will work
This commit is contained in:
2025-11-25 14:08:58 -05:00
parent 22b52abc30
commit bb1d6bbb24
51 changed files with 3798 additions and 460 deletions

View File

@@ -179,4 +179,5 @@
#include "gridfire/engine/views/engine_views.h"
#include "gridfire/engine/procedures/engine_procedures.h"
#include "gridfire/engine/types/engine_types.h"
#include "gridfire/engine/types/engine_types.h"
#include "gridfire/engine/diagnostics/dynamic_engine_diagnostics.h"

View File

@@ -24,23 +24,21 @@ namespace gridfire::engine {
enum class NetworkConstructionFlags : uint32_t {
NONE = 0,
STRONG = 1 << 0, // 1
REACLIB_STRONG = 1 << 0, // 1
BETA_MINUS = 1 << 1, // 2
BETA_PLUS = 1 << 2, // 4
ELECTRON_CAPTURE = 1 << 3, // 8
POSITRON_CAPTURE = 1 << 4, // 16
WRL_BETA_MINUS = 1 << 1, // 2
WRL_BETA_PLUS = 1 << 2, // 4
WRL_ELECTRON_CAPTURE = 1 << 3, // 8
WRL_POSITRON_CAPTURE = 1 << 4, // 16
REACLIB_WEAK = 1 << 5,
WRL_WEAK = BETA_MINUS | BETA_PLUS | ELECTRON_CAPTURE | POSITRON_CAPTURE,
WRL_WEAK = WRL_BETA_MINUS | WRL_BETA_PLUS | WRL_ELECTRON_CAPTURE | WRL_POSITRON_CAPTURE,
REACLIB = STRONG | REACLIB_WEAK,
REACLIB = REACLIB_STRONG | REACLIB_WEAK,
// Currently we default to just reaclib reactions but include both their strong and weak set
DEFAULT = REACLIB,
ALL = STRONG | WRL_WEAK
};
/** @brief Helper function to convert NetworkConstructionFlags to their underlying integer type.
@@ -103,20 +101,20 @@ namespace gridfire::engine {
inline std::string NetworkConstructionFlagsToString(NetworkConstructionFlags flags) {
std::stringstream ss;
constexpr std::array<NetworkConstructionFlags, 6> bases_flags_array = {
NetworkConstructionFlags::STRONG,
NetworkConstructionFlags::BETA_MINUS,
NetworkConstructionFlags::BETA_PLUS,
NetworkConstructionFlags::ELECTRON_CAPTURE,
NetworkConstructionFlags::POSITRON_CAPTURE,
NetworkConstructionFlags::REACLIB_STRONG,
NetworkConstructionFlags::WRL_BETA_MINUS,
NetworkConstructionFlags::WRL_BETA_PLUS,
NetworkConstructionFlags::WRL_ELECTRON_CAPTURE,
NetworkConstructionFlags::WRL_POSITRON_CAPTURE,
NetworkConstructionFlags::REACLIB_WEAK
};
const std::unordered_map<NetworkConstructionFlags, std::string> bases_string_map = {
{NetworkConstructionFlags::STRONG, "Strong"},
{NetworkConstructionFlags::BETA_MINUS, "BetaMinus"},
{NetworkConstructionFlags::BETA_PLUS, "BetaPlus"},
{NetworkConstructionFlags::ELECTRON_CAPTURE, "ElectronCapture"},
{NetworkConstructionFlags::POSITRON_CAPTURE, "PositronCapture"},
{NetworkConstructionFlags::REACLIB_STRONG, "Strong"},
{NetworkConstructionFlags::WRL_BETA_MINUS, "BetaMinus"},
{NetworkConstructionFlags::WRL_BETA_PLUS, "BetaPlus"},
{NetworkConstructionFlags::WRL_ELECTRON_CAPTURE, "ElectronCapture"},
{NetworkConstructionFlags::WRL_POSITRON_CAPTURE, "PositronCapture"},
{NetworkConstructionFlags::REACLIB_WEAK, "ReaclibWeak"}
};

View File

@@ -31,54 +31,4 @@ namespace gridfire::engine {
GraphEngine& engine,
const std::optional<std::vector<reaction::ReactionType>>& ignoredReactionTypes
);
/**
* @brief Computes the destruction rate constant for a specific species.
*
* Calculates the sum of molar reaction flows for all reactions where the species
* is a reactant (negative stoichiometry) after scaling its abundance to unity.
*
* @param engine Engine providing the current set of network reactions and flow calculations.
* @param species The atomic species whose destruction rate is computed.
* @param composition Current composition providing abundances for all species.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density of the medium.
* @param reactionTypesToIgnore types of reactions to ignore during calculation.
* @pre Y.size() matches engine.getNetworkReactions().size() mapping species order.
* @post Returned rate constant is non-negative.
* @return Sum of absolute stoichiometry-weighted destruction flows for the species.
*/
double calculateDestructionRateConstant(
const DynamicEngine& engine,
const fourdst::atomic::Species& species,
const fourdst::composition::Composition& composition,
double T9,
double rho,
const std::optional<std::vector<reaction::ReactionType>> &reactionTypesToIgnore
);
/**
* @brief Computes the creation rate for a specific species.
*
* Sums molar reaction flows for all reactions where the species
* appears as a product (positive stoichiometry).
*
* @param engine Engine providing the current set of network reactions and flow calculations.
* @param species The atomic species whose creation rate is computed.
* @param composition Composition object containing current abundances.
* @param T9 Temperature in units of 10^9 K.
* @param rho Density of the medium.
* @param reactionTypesToIgnore types of reactions to ignore during calculation.
* @pre Y.size() matches engine.getNetworkReactions().size() mapping species order.
* @post Returned creation rate is non-negative.
* @return Sum of stoichiometry-weighted creation flows for the species.
*/
double calculateCreationRate(
const DynamicEngine& engine,
const fourdst::atomic::Species& species,
const fourdst::composition::Composition& composition,
double T9,
double rho,
const std::optional<std::vector<reaction::ReactionType>> &reactionTypesToIgnore
);
}

View File

@@ -1,5 +1,7 @@
#pragma once
#include <string_view>
namespace gridfire::engine {
/**
* @enum EngineTypes

View File

@@ -153,7 +153,7 @@ namespace gridfire::policy {
* if (s != NetworkPolicyStatus::INITIALIZED_VERIFIED) { // handle error }
* @endcode
*/
[[nodiscard]] virtual NetworkPolicyStatus getStatus() const = 0;
[[nodiscard]] virtual NetworkPolicyStatus get_status() const = 0;
[[nodiscard]] virtual const std::vector<std::unique_ptr<engine::DynamicEngine>> &get_engine_stack() const = 0;

View File

@@ -141,7 +141,7 @@ namespace gridfire::policy {
* @brief Gets the current status of the policy.
* @return NetworkPolicyStatus The construction and verification status.
*/
[[nodiscard]] NetworkPolicyStatus getStatus() const override;
[[nodiscard]] NetworkPolicyStatus get_status() const override;
[[nodiscard]] const std::vector<std::unique_ptr<engine::DynamicEngine>> &get_engine_stack() const override;

View File

@@ -15,7 +15,7 @@ namespace gridfire::engine::diagnostics {
const double relTol,
const double absTol,
const size_t top_n,
bool json
const bool json
) {
struct SpeciesError {
std::string name;

View File

@@ -63,7 +63,7 @@ namespace {
parent_species.z() - 1
);
if (downProduct.has_value()) { // Only add the reaction if the Species map contains the product
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::BETA_PLUS)) {
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::WRL_BETA_PLUS)) {
weak_reaction_pool.add_reaction(
std::make_unique<gridfire::rates::weak::WeakReaction>(
parent_species,
@@ -72,7 +72,7 @@ namespace {
)
);
}
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::ELECTRON_CAPTURE)) {
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::WRL_ELECTRON_CAPTURE)) {
weak_reaction_pool.add_reaction(
std::make_unique<gridfire::rates::weak::WeakReaction>(
parent_species,
@@ -83,7 +83,7 @@ namespace {
}
}
if (upProduct.has_value()) { // Only add the reaction if the Species map contains the product
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::BETA_MINUS)) {
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::WRL_BETA_MINUS)) {
weak_reaction_pool.add_reaction(
std::make_unique<gridfire::rates::weak::WeakReaction>(
parent_species,
@@ -92,7 +92,7 @@ namespace {
)
);
}
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::POSITRON_CAPTURE)) {
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::WRL_POSITRON_CAPTURE)) {
weak_reaction_pool.add_reaction(
std::make_unique<gridfire::rates::weak::WeakReaction>(
parent_species,
@@ -111,7 +111,7 @@ namespace {
const gridfire::engine::NetworkConstructionFlags reaction_types
) {
gridfire::reaction::ReactionSet strong_reaction_pool;
if (has_flag(reaction_types, gridfire::engine::NetworkConstructionFlags::STRONG)) {
if (has_flag(reaction_types, gridfire::engine::NetworkConstructionFlags::REACLIB_STRONG)) {
const auto& allReaclibReactions = gridfire::reaclib::get_all_reaclib_reactions();
for (const auto& reaction : allReaclibReactions) {
const bool isWeakReaction = reaclib_reaction_is_weak(*reaction);
@@ -129,11 +129,11 @@ namespace {
bool validate_unique_weak_set(gridfire::engine::NetworkConstructionFlags flag) {
// This method ensures that weak reactions will only be fetched from either reaclib or the weak reaction library (WRL)
// but not both
std::array<gridfire::engine::NetworkConstructionFlags, 4> WRL_Flags = {
gridfire::engine::NetworkConstructionFlags::BETA_PLUS,
gridfire::engine::NetworkConstructionFlags::ELECTRON_CAPTURE,
gridfire::engine::NetworkConstructionFlags::POSITRON_CAPTURE,
gridfire::engine::NetworkConstructionFlags::BETA_MINUS
const std::array<gridfire::engine::NetworkConstructionFlags, 4> WRL_Flags = {
gridfire::engine::NetworkConstructionFlags::WRL_BETA_PLUS,
gridfire::engine::NetworkConstructionFlags::WRL_ELECTRON_CAPTURE,
gridfire::engine::NetworkConstructionFlags::WRL_POSITRON_CAPTURE,
gridfire::engine::NetworkConstructionFlags::WRL_BETA_MINUS
};
if (!has_flag(flag, gridfire::engine::NetworkConstructionFlags::REACLIB_WEAK)) {

View File

@@ -92,7 +92,7 @@ namespace gridfire::policy {
return std::make_unique<partition::CompositePartitionFunction>(partitionFunction);
}
inline NetworkPolicyStatus MainSequencePolicy::getStatus() const {
inline NetworkPolicyStatus MainSequencePolicy::get_status() const {
return m_status;
}

View File

@@ -3,7 +3,6 @@
#include "types/bindings.h"
#include "partition/bindings.h"
#include "expectations/bindings.h"
#include "engine/bindings.h"
#include "exceptions/bindings.h"
#include "io/bindings.h"
@@ -11,8 +10,9 @@
#include "screening/bindings.h"
#include "solver/bindings.h"
#include "utils/bindings.h"
#include "policy/bindings.h"
PYBIND11_MODULE(gridfire, m) {
PYBIND11_MODULE(_gridfire, m) {
m.doc() = "Python bindings for the fourdst utility modules which are a part of the 4D-STAR project.";
pybind11::module::import("fourdst.constants");
@@ -26,9 +26,6 @@ PYBIND11_MODULE(gridfire, m) {
auto partitionMod = m.def_submodule("partition", "GridFire partition function bindings");
register_partition_bindings(partitionMod);
auto expectationMod = m.def_submodule("expectations", "GridFire expectations bindings");
register_expectation_bindings(expectationMod);
auto reactionMod = m.def_submodule("reaction", "GridFire reaction bindings");
register_reaction_bindings(reactionMod);
@@ -47,6 +44,9 @@ PYBIND11_MODULE(gridfire, m) {
auto solverMod = m.def_submodule("solver", "GridFire numerical solver bindings");
register_solver_bindings(solverMod);
auto policyMod = m.def_submodule("policy", "GridFire network policy bindings");
register_policy_bindings(policyMod);
auto utilsMod = m.def_submodule("utils", "GridFire utility method bindings");
register_utils_bindings(utilsMod);
}

View File

@@ -5,8 +5,8 @@
#include "bindings.h"
#include "gridfire/engine/engine.h"
#include "gridfire/engine/diagnostics/dynamic_engine_diagnostics.h"
#include "gridfire/exceptions/exceptions.h"
#include "pybind11/numpy.h"
#include "trampoline/py_engine.h"
@@ -15,21 +15,21 @@ namespace py = pybind11;
namespace {
template <typename T>
concept IsDynamicEngine = std::is_base_of_v<gridfire::DynamicEngine, T>;
concept IsDynamicEngine = std::is_base_of_v<gridfire::engine::DynamicEngine, T>;
template <IsDynamicEngine T, IsDynamicEngine BaseT>
void registerDynamicEngineDefs(py::class_<T, BaseT> pyClass) {
pyClass.def(
"calculateRHSAndEnergy",
[](
const gridfire::DynamicEngine& self,
const gridfire::engine::DynamicEngine& self,
const fourdst::composition::Composition& comp,
const double T9,
const double rho
) {
auto result = self.calculateRHSAndEnergy(comp, T9, rho);
if (!result.has_value()) {
throw gridfire::exceptions::StaleEngineError("Engine reports stale state, call update().");
throw gridfire::exceptions::EngineError(std::format("calculateRHSAndEnergy returned a potentially recoverable error {}", gridfire::engine::EngineStatus_to_string(result.error())));
}
return result.value();
},
@@ -39,21 +39,32 @@ namespace {
"Calculate the right-hand side (dY/dt) and energy generation rate."
)
.def("calculateEpsDerivatives",
&gridfire::DynamicEngine::calculateEpsDerivatives,
&gridfire::engine::DynamicEngine::calculateEpsDerivatives,
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
"Calculate deps/dT and deps/drho"
)
.def("generateJacobianMatrix",
py::overload_cast<const fourdst::composition::Composition&, double, double>(&T::generateJacobianMatrix, py::const_),
[](const gridfire::engine::DynamicEngine& self,
const fourdst::composition::Composition& comp,
const double T9,
const double rho) -> gridfire::engine::NetworkJacobian {
return self.generateJacobianMatrix(comp, T9, rho);
},
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
"Generate the Jacobian matrix for the current state."
)
.def("generateJacobianMatrix",
py::overload_cast<const fourdst::composition::Composition&, double, double, const std::vector<fourdst::atomic::Species>&>(&T::generateJacobianMatrix, py::const_),
[](const gridfire::engine::DynamicEngine& self,
const fourdst::composition::Composition& comp,
const double T9,
const double rho,
const std::vector<fourdst::atomic::Species>& activeSpecies) -> gridfire::engine::NetworkJacobian {
return self.generateJacobianMatrix(comp, T9, rho, activeSpecies);
},
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
@@ -61,7 +72,13 @@ namespace {
"Generate the jacobian matrix only for the subset of the matrix representing the active species."
)
.def("generateJacobianMatrix",
py::overload_cast<const fourdst::composition::Composition&, double, double, const gridfire::SparsityPattern&>(&T::generateJacobianMatrix, py::const_),
[](const gridfire::engine::DynamicEngine& self,
const fourdst::composition::Composition& comp,
const double T9,
const double rho,
const gridfire::engine::SparsityPattern& sparsityPattern) -> gridfire::engine::NetworkJacobian {
return self.generateJacobianMatrix(comp, T9, rho, sparsityPattern);
},
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
@@ -73,7 +90,7 @@ namespace {
)
.def("calculateMolarReactionFlow",
[](
const gridfire::DynamicEngine& self,
const gridfire::engine::DynamicEngine& self,
const gridfire::reaction::Reaction& reaction,
const fourdst::composition::Composition& comp,
const double T9,
@@ -97,11 +114,6 @@ namespace {
py::arg("reactions"),
"Set the network reactions to a new set of reactions."
)
.def("getJacobianMatrixEntry", &T::getJacobianMatrixEntry,
py::arg("rowSpecies"),
py::arg("colSpecies"),
"Get an entry from the previously generated Jacobian matrix."
)
.def("getStoichiometryMatrixEntry", &T::getStoichiometryMatrixEntry,
py::arg("species"),
py::arg("reaction"),
@@ -109,14 +121,14 @@ namespace {
)
.def("getSpeciesTimescales",
[](
const gridfire::DynamicEngine& self,
const gridfire::engine::DynamicEngine& self,
const fourdst::composition::Composition& comp,
const double T9,
const double rho
) -> std::unordered_map<fourdst::atomic::Species, double> {
const auto result = self.getSpeciesTimescales(comp, T9, rho);
if (!result.has_value()) {
throw gridfire::exceptions::StaleEngineError("Engine reports stale state, call update().");
throw gridfire::exceptions::EngineError(std::format("getSpeciesTimescales has returned a potentially recoverable error {}", gridfire::engine::EngineStatus_to_string(result.error())));
}
return result.value();
},
@@ -127,14 +139,14 @@ namespace {
)
.def("getSpeciesDestructionTimescales",
[](
const gridfire::DynamicEngine& self,
const gridfire::engine::DynamicEngine& self,
const fourdst::composition::Composition& comp,
const double T9,
const double rho
) -> std::unordered_map<fourdst::atomic::Species, double> {
const auto result = self.getSpeciesDestructionTimescales(comp, T9, rho);
if (!result.has_value()) {
throw gridfire::exceptions::StaleEngineError("Engine reports stale state, call update().");
throw gridfire::exceptions::EngineError(std::format("getSpeciesDestructionTimescales has returned a potentially recoverable error {}", gridfire::engine::EngineStatus_to_string(result.error())));
}
return result.value();
},
@@ -179,7 +191,7 @@ namespace {
.def("rebuild",
&T::rebuild,
py::arg("composition"),
py::arg("depth") = gridfire::NetworkBuildDepth::Full,
py::arg("depth") = gridfire::engine::NetworkBuildDepth::Full,
"Rebuild the engine with a new composition and build depth."
)
.def("isStale",
@@ -190,7 +202,14 @@ namespace {
.def("collectComposition",
&T::collectComposition,
py::arg("composition"),
py::arg("T9"),
py::arg("rho"),
"Recursively collect composition from current engine and any sub engines if they exist."
)
.def("getSpeciesStatus",
&T::getSpeciesStatus,
py::arg("species"),
"Get the status of a species in the network."
);
}
@@ -206,11 +225,11 @@ void register_engine_bindings(py::module &m) {
void register_base_engine_bindings(const pybind11::module &m) {
py::class_<gridfire::StepDerivatives<double>>(m, "StepDerivatives")
.def_readonly("dYdt", &gridfire::StepDerivatives<double>::dydt, "The right-hand side (dY/dt) of the ODE system.")
.def_readonly("energy", &gridfire::StepDerivatives<double>::nuclearEnergyGenerationRate, "The energy generation rate.");
py::class_<gridfire::engine::StepDerivatives<double>>(m, "StepDerivatives")
.def_readonly("dYdt", &gridfire::engine::StepDerivatives<double>::dydt, "The right-hand side (dY/dt) of the ODE system.")
.def_readonly("energy", &gridfire::engine::StepDerivatives<double>::nuclearEnergyGenerationRate, "The energy generation rate.");
py::class_<gridfire::SparsityPattern> py_sparsity_pattern(m, "SparsityPattern");
py::class_<gridfire::engine::SparsityPattern> py_sparsity_pattern(m, "SparsityPattern");
abs_stype_register_engine_bindings(m);
abs_stype_register_dynamic_engine_bindings(m);
@@ -218,148 +237,219 @@ void register_base_engine_bindings(const pybind11::module &m) {
}
void abs_stype_register_engine_bindings(const pybind11::module &m) {
py::class_<gridfire::Engine, PyEngine>(m, "Engine");
py::class_<gridfire::engine::Engine, PyEngine>(m, "Engine");
}
void abs_stype_register_dynamic_engine_bindings(const pybind11::module &m) {
const auto a = py::class_<gridfire::DynamicEngine, PyDynamicEngine>(m, "DynamicEngine");
const auto a = py::class_<gridfire::engine::DynamicEngine, PyDynamicEngine>(m, "DynamicEngine");
}
void register_engine_procedural_bindings(pybind11::module &m) {
auto procedures = m.def_submodule("procedures", "Procedural functions associated with engine module");
register_engine_construction_bindings(procedures);
register_engine_construction_bindings(procedures);
register_engine_construction_bindings(m);
register_engine_priming_bindings(m);
}
void register_engine_diagnostic_bindings(pybind11::module &m) {
auto diagnostics = m.def_submodule("diagnostics", "A submodule for engine diagnostics");
diagnostics.def("report_limiting_species",
&gridfire::diagnostics::report_limiting_species,
&gridfire::engine::diagnostics::report_limiting_species,
py::arg("engine"),
py::arg("Y_full"),
py::arg("E_full"),
py::arg("dydt_full"),
py::arg("relTol"),
py::arg("absTol"),
py::arg("top_n") = 10
py::arg("top_n"),
py::arg("json")
);
diagnostics.def("inspect_species_balance",
&gridfire::diagnostics::inspect_species_balance,
&gridfire::engine::diagnostics::inspect_species_balance,
py::arg("engine"),
py::arg("species_name"),
py::arg("comp"),
py::arg("T9"),
py::arg("rho")
py::arg("rho"),
py::arg("json")
);
diagnostics.def("inspect_jacobian_stiffness",
&gridfire::diagnostics::inspect_jacobian_stiffness,
&gridfire::engine::diagnostics::inspect_jacobian_stiffness,
py::arg("engine"),
py::arg("comp"),
py::arg("T9"),
py::arg("rho")
py::arg("rho"),
py::arg("json")
);
}
void register_engine_construction_bindings(pybind11::module &m) {
m.def("build_nuclear_network", &gridfire::build_nuclear_network,
py::enum_<gridfire::engine::NetworkConstructionFlags>(m, "NetworkConstructionFlags")
.value("NONE", gridfire::engine::NetworkConstructionFlags::NONE, "No special construction flags.")
.value("REACLIB_STRONG", gridfire::engine::NetworkConstructionFlags::REACLIB_STRONG, "Include strong reactions from reaclib.")
.value("WRL_BETA_MINUS", gridfire::engine::NetworkConstructionFlags::WRL_BETA_MINUS, "Include beta-minus decay reactions from weak rate library.")
.value("WRL_BETA_PLUS", gridfire::engine::NetworkConstructionFlags::WRL_BETA_PLUS, "Include beta-plus decay reactions from weak rate library.")
.value("WRL_ELECTRON_CAPTURE", gridfire::engine::NetworkConstructionFlags::WRL_ELECTRON_CAPTURE, "Include electron capture reactions from weak rate library.")
.value("WRL_POSITRON_CAPTURE", gridfire::engine::NetworkConstructionFlags::WRL_POSITRON_CAPTURE, "Include positron capture reactions from weak rate library.")
.value("REACLIB_WEAK", gridfire::engine::NetworkConstructionFlags::REACLIB_WEAK, "Include weak reactions from reaclib.")
.value("WRL_WEAK", gridfire::engine::NetworkConstructionFlags::WRL_WEAK, "Include all weak reactions from weak rate library.")
.value("REACLIB", gridfire::engine::NetworkConstructionFlags::REACLIB, "Include all reactions from reaclib.")
.value("DEFAULT", gridfire::engine::NetworkConstructionFlags::DEFAULT, "Default construction flags (Reaclib strong and weak).")
.export_values()
.def("__repr__", [](const gridfire::engine::NetworkConstructionFlags& flags) {
return gridfire::engine::NetworkConstructionFlagsToString(flags);
});
m.def("build_nuclear_network", &gridfire::engine::build_nuclear_network,
py::arg("composition"),
py::arg("weakInterpolator"),
py::arg("maxLayers") = gridfire::NetworkBuildDepth::Full,
py::arg("reverse") = false,
py::arg("maxLayers") = gridfire::engine::NetworkBuildDepth::Full,
py::arg("ReactionTypes") = gridfire::engine::NetworkConstructionFlags::DEFAULT,
"Build a nuclear network from a composition using all archived reaction data."
);
}
void register_engine_priming_bindings(pybind11::module &m) {
m.def("calculateDestructionRateConstant",
&gridfire::calculateDestructionRateConstant,
m.def("primeNetwork",
&gridfire::engine::primeNetwork,
py::arg("netIn"),
py::arg("engine"),
py::arg("species"),
py::arg("composition"),
py::arg("T9"),
py::arg("rho"),
py::arg("reactionTypesToIgnore")
);
m.def("calculateCreationRate",
&gridfire::calculateCreationRate,
py::arg("engine"),
py::arg("species"),
py::arg("composition"),
py::arg("T9"),
py::arg("rho"),
py::arg("reactionTypesToIgnore")
py::arg("ignoredReactionTypes") = std::nullopt,
"Prime a network with a short timescale ignition"
);
}
void register_engine_type_bindings(pybind11::module &m) {
auto types = m.def_submodule("types", "Types associated with engine module");
register_engine_building_type_bindings(types);
register_engine_reporting_type_bindings(types);
register_engine_building_type_bindings(m);
register_engine_reporting_type_bindings(m);
register_engine_types_bindings(m);
register_jacobian_type_bindings(m);
}
void register_engine_building_type_bindings(pybind11::module &m) {
py::enum_<gridfire::NetworkBuildDepth>(m, "NetworkBuildDepth")
.value("Full", gridfire::NetworkBuildDepth::Full, "Full network build depth")
.value("Shallow", gridfire::NetworkBuildDepth::Shallow, "Shallow network build depth")
.value("SecondOrder", gridfire::NetworkBuildDepth::SecondOrder, "Second order network build depth")
.value("ThirdOrder", gridfire::NetworkBuildDepth::ThirdOrder, "Third order network build depth")
.value("FourthOrder", gridfire::NetworkBuildDepth::FourthOrder, "Fourth order network build depth")
.value("FifthOrder", gridfire::NetworkBuildDepth::FifthOrder, "Fifth order network build depth")
void register_engine_building_type_bindings(const pybind11::module &m) {
py::enum_<gridfire::engine::NetworkBuildDepth>(m, "NetworkBuildDepth")
.value("Full", gridfire::engine::NetworkBuildDepth::Full, "Full network build depth")
.value("Shallow", gridfire::engine::NetworkBuildDepth::Shallow, "Shallow network build depth")
.value("SecondOrder", gridfire::engine::NetworkBuildDepth::SecondOrder, "Second order network build depth")
.value("ThirdOrder", gridfire::engine::NetworkBuildDepth::ThirdOrder, "Third order network build depth")
.value("FourthOrder", gridfire::engine::NetworkBuildDepth::FourthOrder, "Fourth order network build depth")
.value("FifthOrder", gridfire::engine::NetworkBuildDepth::FifthOrder, "Fifth order network build depth")
.export_values();
py::class_<gridfire::BuildDepthType> py_build_depth_type(m, "BuildDepthType");
py::class_<gridfire::engine::BuildDepthType> py_build_depth_type(m, "BuildDepthType");
}
void register_engine_reporting_type_bindings(pybind11::module &m) {
py::enum_<gridfire::PrimingReportStatus>(m, "PrimingReportStatus")
.value("FULL_SUCCESS", gridfire::PrimingReportStatus::FULL_SUCCESS, "Priming was full successful.")
.value("NO_SPECIES_TO_PRIME", gridfire::PrimingReportStatus::NO_SPECIES_TO_PRIME, "No species to prime.")
.value("MAX_ITERATIONS_REACHED", gridfire::PrimingReportStatus::MAX_ITERATIONS_REACHED, "Maximum iterations reached during priming.")
.value("FAILED_TO_FINALIZE_COMPOSITION", gridfire::PrimingReportStatus::FAILED_TO_FINALIZE_COMPOSITION, "Failed to finalize the composition after priming.")
.value("FAILED_TO_FIND_CREATION_CHANNEL", gridfire::PrimingReportStatus::FAILED_TO_FIND_CREATION_CHANNEL, "Failed to find a creation channel for the priming species.")
.value("FAILED_TO_FIND_PRIMING_REACTIONS", gridfire::PrimingReportStatus::FAILED_TO_FIND_PRIMING_REACTIONS, "Failed to find priming reactions for the species.")
.value("BASE_NETWORK_TOO_SHALLOW", gridfire::PrimingReportStatus::BASE_NETWORK_TOO_SHALLOW, "The base network is too shallow for priming.")
void register_engine_reporting_type_bindings(const pybind11::module &m) {
py::enum_<gridfire::engine::PrimingReportStatus>(m, "PrimingReportStatus")
.value("FULL_SUCCESS", gridfire::engine::PrimingReportStatus::SUCCESS, "Priming was full successful.")
.value("NO_SPECIES_TO_PRIME", gridfire::engine::PrimingReportStatus::SOLVER_FAILURE, "Solver Failed to converge during priming.")
.value("MAX_ITERATIONS_REACHED", gridfire::engine::PrimingReportStatus::ALREADY_PRIMED, "Engine has already been primed.")
.export_values()
.def("__repr__", [](const gridfire::PrimingReportStatus& status) {
.def("__repr__", [](const gridfire::engine::PrimingReportStatus& status) {
std::stringstream ss;
ss << gridfire::PrimingReportStatusStrings.at(status) << "\n";
ss << gridfire::engine::PrimingReportStatusStrings.at(status) << "\n";
return ss.str();
},
"String representation of the PrimingReport."
);
py::class_<gridfire::PrimingReport>(m, "PrimingReport")
.def_readonly("success", &gridfire::PrimingReport::success, "Indicates if the priming was successful.")
.def_readonly("massFractionChanges", &gridfire::PrimingReport::massFractionChanges, "Map of species to their mass fraction changes after priming.")
.def_readonly("primedComposition", &gridfire::PrimingReport::primedComposition, "The composition after priming.")
.def_readonly("status", &gridfire::PrimingReport::status, "Status message from the priming process.")
.def("__repr__", [](const gridfire::PrimingReport& report) {
py::class_<gridfire::engine::PrimingReport>(m, "PrimingReport")
.def_readonly("success", &gridfire::engine::PrimingReport::success, "Indicates if the priming was successful.")
.def_readonly("primedComposition", &gridfire::engine::PrimingReport::primedComposition, "The composition after priming.")
.def_readonly("status", &gridfire::engine::PrimingReport::status, "Status message from the priming process.")
.def("__repr__", [](const gridfire::engine::PrimingReport& report) {
std::stringstream ss;
ss << report;
return ss.str();
}
);
py::enum_<gridfire::engine::SpeciesStatus>(m, "SpeciesStatus")
.value("ACTIVE", gridfire::engine::SpeciesStatus::ACTIVE, "Species is active in the network.")
.value("EQUILIBRIUM", gridfire::engine::SpeciesStatus::EQUILIBRIUM, "Species is in equilibrium.")
.value("INACTIVE_FLOW", gridfire::engine::SpeciesStatus::INACTIVE_FLOW, "Species is inactive due to flow.")
.value("NOT_PRESENT", gridfire::engine::SpeciesStatus::NOT_PRESENT, "Species is not present in the network.")
.export_values()
.def("__repr__", [](const gridfire::engine::SpeciesStatus& status) {
return gridfire::engine::SpeciesStatus_to_string(status);
});
}
void register_engine_types_bindings(const pybind11::module &m) {
py::enum_<gridfire::engine::EngineTypes>(m, "EngineTypes")
.value("GRAPH_ENGINE", gridfire::engine::EngineTypes::GRAPH_ENGINE, "The standard graph-based engine.")
.value("ADAPTIVE_ENGINE_VIEW", gridfire::engine::EngineTypes::ADAPTIVE_ENGINE_VIEW, "An engine that adapts based on certain criteria.")
.value("MULTISCALE_PARTITIONING_ENGINE_VIEW", gridfire::engine::EngineTypes::MULTISCALE_PARTITIONING_ENGINE_VIEW, "An engine that partitions the system at multiple scales.")
.value("PRIMING_ENGINE_VIEW", gridfire::engine::EngineTypes::PRIMING_ENGINE_VIEW, "An engine that uses a priming strategy for simulations.")
.value("DEFINED_ENGINE_VIEW", gridfire::engine::EngineTypes::DEFINED_ENGINE_VIEW, "An engine defined by user specifications.")
.value("FILE_DEFINED_ENGINE_VIEW", gridfire::engine::EngineTypes::FILE_DEFINED_ENGINE_VIEW, "An engine defined through external files.")
.export_values()
.def("__repr__", [](const gridfire::engine::EngineTypes& type) {
return std::string(gridfire::engine::engine_type_to_string(type));
},
"String representation of the EngineTypes."
);
}
void register_jacobian_type_bindings(pybind11::module &m) {
py::class_<gridfire::engine::NetworkJacobian>(m, "NetworkJacobian")
.def("rank", &gridfire::engine::NetworkJacobian::rank, "Get the rank of the Jacobian matrix.")
.def("nnz", &gridfire::engine::NetworkJacobian::nnz, "Get the number of non-zero entries in the Jacobian matrix.")
.def("singular", &gridfire::engine::NetworkJacobian::singular, "Check if the Jacobian matrix is singular.")
.def("infs", &gridfire::engine::NetworkJacobian::infs, "Get all infinite entries in the Jacobian matrix.")
.def("nans", &gridfire::engine::NetworkJacobian::nans, "Get all NaN entries in the Jacobian matrix.")
.def("data", &gridfire::engine::NetworkJacobian::data, "Get the underlying sparse matrix data.")
.def("mapping", &gridfire::engine::NetworkJacobian::mapping, "Get the species-to-index mapping.")
.def("shape", &gridfire::engine::NetworkJacobian::shape, "Get the shape of the Jacobian matrix as (rows, columns).")
.def("to_csv", &gridfire::engine::NetworkJacobian::to_csv, py::arg("filename"), "Export the Jacobian matrix to a CSV file.")
.def("__getitem__", [](const gridfire::engine::NetworkJacobian &self, const std::pair<fourdst::atomic::Species, fourdst::atomic::Species>& speciesPair) {
return self(speciesPair.first, speciesPair.second);
}, py::arg("key"), "Get an entry from the Jacobian matrix using species identifiers.")
.def("__getitem__", [](const gridfire::engine::NetworkJacobian &self, const std::pair<size_t, size_t>& indexPair) {
return self(indexPair.first, indexPair.second);
}, py::arg("key"), "Get an entry from the Jacobian matrix using indices.")
.def("__setitem__", [](gridfire::engine::NetworkJacobian &self, const std::pair<fourdst::atomic::Species, fourdst::atomic::Species>& speciesPair, double value) {
self.set(speciesPair.first, speciesPair.second, value);
}, py::arg("key"), py::arg("value"), "Set an entry in the Jacobian matrix using species identifiers.")
.def("__setitem__", [](gridfire::engine::NetworkJacobian &self, const std::pair<size_t, size_t>& indexPair, double value) {
self.set(indexPair.first, indexPair.second, value);
}, py::arg("key"), py::arg("value"), "Set an entry in the Jacobian matrix using indices.")
.def("to_numpy", [](const gridfire::engine::NetworkJacobian &self) {
auto denseMatrix = Eigen::MatrixXd(self.data());
return pybind11::array_t<double>(
{std::get<0>(self.shape()), std::get<1>(self.shape())},
{sizeof(double) * std::get<1>(self.shape()), sizeof(double)},
denseMatrix.data()
);
}, "Convert the Jacobian matrix to a NumPy array.");
m.def(
"regularize_jacobian",
[](const gridfire::engine::NetworkJacobian& jac, const fourdst::composition::Composition& comp) {
return regularize_jacobian(jac, comp, std::nullopt);
},
py::arg("jacobian"),
py::arg("composition"),
"regularize_jacobian"
);
}
void con_stype_register_graph_engine_bindings(const pybind11::module &m) {
auto py_graph_engine_bindings = py::class_<gridfire::GraphEngine, gridfire::DynamicEngine>(m, "GraphEngine");
auto py_graph_engine_bindings = py::class_<gridfire::engine::GraphEngine, gridfire::engine::DynamicEngine>(m, "GraphEngine");
// Register the Graph Engine Specific Bindings
py_graph_engine_bindings.def(py::init<const fourdst::composition::Composition &, const gridfire::BuildDepthType>(),
py_graph_engine_bindings.def(py::init<const fourdst::composition::Composition &, const gridfire::engine::BuildDepthType>(),
py::arg("composition"),
py::arg("depth") = gridfire::NetworkBuildDepth::Full,
py::arg("depth") = gridfire::engine::NetworkBuildDepth::Full,
"Initialize GraphEngine with a composition and build depth."
);
py_graph_engine_bindings.def(py::init<const fourdst::composition::Composition &,const gridfire::partition::PartitionFunction &, const gridfire::BuildDepthType>(),
py_graph_engine_bindings.def(py::init<const fourdst::composition::Composition &,const gridfire::partition::PartitionFunction &, const gridfire::engine::BuildDepthType>(),
py::arg("composition"),
py::arg("partitionFunction"),
py::arg("depth") = gridfire::NetworkBuildDepth::Full,
py::arg("depth") = gridfire::engine::NetworkBuildDepth::Full,
"Initialize GraphEngine with a composition, partition function and build depth."
);
py_graph_engine_bindings.def(py::init<const gridfire::reaction::ReactionSet &>(),
@@ -367,54 +457,66 @@ void con_stype_register_graph_engine_bindings(const pybind11::module &m) {
"Initialize GraphEngine with a set of reactions."
);
py_graph_engine_bindings.def_static("getNetReactionStoichiometry",
&gridfire::GraphEngine::getNetReactionStoichiometry,
&gridfire::engine::GraphEngine::getNetReactionStoichiometry,
py::arg("reaction"),
"Get the net stoichiometry for a given reaction."
);
py_graph_engine_bindings.def("getSpeciesTimescales",
py::overload_cast<const fourdst::composition::Composition&, double, double, const gridfire::reaction::ReactionSet&>(&gridfire::GraphEngine::getSpeciesTimescales, py::const_),
[](const gridfire::engine::GraphEngine& self,
const fourdst::composition::Composition& composition,
const double T9,
const double rho,
const gridfire::reaction::ReactionSet& activeReactions) {
return self.getSpeciesTimescales(composition, T9, rho, activeReactions);
},
py::arg("composition"),
py::arg("T9"),
py::arg("rho"),
py::arg("activeReactions")
);
py_graph_engine_bindings.def("getSpeciesDestructionTimescales",
py::overload_cast<const fourdst::composition::Composition&, double, double, const gridfire::reaction::ReactionSet&>(&gridfire::GraphEngine::getSpeciesDestructionTimescales, py::const_),
[](const gridfire::engine::GraphEngine& self,
const fourdst::composition::Composition& composition,
const double T9,
const double rho,
const gridfire::reaction::ReactionSet& activeReactions) {
return self.getSpeciesDestructionTimescales(composition, T9, rho, activeReactions);
},
py::arg("composition"),
py::arg("T9"),
py::arg("rho"),
py::arg("activeReactions")
);
py_graph_engine_bindings.def("involvesSpecies",
&gridfire::GraphEngine::involvesSpecies,
&gridfire::engine::GraphEngine::involvesSpecies,
py::arg("species"),
"Check if a given species is involved in the network."
);
py_graph_engine_bindings.def("exportToDot",
&gridfire::GraphEngine::exportToDot,
&gridfire::engine::GraphEngine::exportToDot,
py::arg("filename"),
"Export the network to a DOT file for visualization."
);
py_graph_engine_bindings.def("exportToCSV",
&gridfire::GraphEngine::exportToCSV,
&gridfire::engine::GraphEngine::exportToCSV,
py::arg("filename"),
"Export the network to a CSV file for analysis."
);
py_graph_engine_bindings.def("setPrecomputation",
&gridfire::GraphEngine::setPrecomputation,
&gridfire::engine::GraphEngine::setPrecomputation,
py::arg("precompute"),
"Enable or disable precomputation for the engine."
);
py_graph_engine_bindings.def("isPrecomputationEnabled",
&gridfire::GraphEngine::isPrecomputationEnabled,
&gridfire::engine::GraphEngine::isPrecomputationEnabled,
"Check if precomputation is enabled for the engine."
);
py_graph_engine_bindings.def("getPartitionFunction",
&gridfire::GraphEngine::getPartitionFunction,
&gridfire::engine::GraphEngine::getPartitionFunction,
"Get the partition function used by the engine."
);
py_graph_engine_bindings.def("calculateReverseRate",
&gridfire::GraphEngine::calculateReverseRate,
&gridfire::engine::GraphEngine::calculateReverseRate,
py::arg("reaction"),
py::arg("T9"),
py::arg("rho"),
@@ -422,7 +524,7 @@ void con_stype_register_graph_engine_bindings(const pybind11::module &m) {
"Calculate the reverse rate for a given reaction at a specific temperature, density, and composition."
);
py_graph_engine_bindings.def("calculateReverseRateTwoBody",
&gridfire::GraphEngine::calculateReverseRateTwoBody,
&gridfire::engine::GraphEngine::calculateReverseRateTwoBody,
py::arg("reaction"),
py::arg("T9"),
py::arg("forwardRate"),
@@ -430,7 +532,7 @@ void con_stype_register_graph_engine_bindings(const pybind11::module &m) {
"Calculate the reverse rate for a two-body reaction at a specific temperature."
);
py_graph_engine_bindings.def("calculateReverseRateTwoBodyDerivative",
&gridfire::GraphEngine::calculateReverseRateTwoBodyDerivative,
&gridfire::engine::GraphEngine::calculateReverseRateTwoBodyDerivative,
py::arg("reaction"),
py::arg("T9"),
py::arg("rho"),
@@ -439,126 +541,96 @@ void con_stype_register_graph_engine_bindings(const pybind11::module &m) {
"Calculate the derivative of the reverse rate for a two-body reaction at a specific temperature."
);
py_graph_engine_bindings.def("isUsingReverseReactions",
&gridfire::GraphEngine::isUsingReverseReactions,
&gridfire::engine::GraphEngine::isUsingReverseReactions,
"Check if the engine is using reverse reactions."
);
py_graph_engine_bindings.def("setUseReverseReactions",
&gridfire::GraphEngine::setUseReverseReactions,
&gridfire::engine::GraphEngine::setUseReverseReactions,
py::arg("useReverse"),
"Enable or disable the use of reverse reactions in the engine."
);
// Register the general dynamic engine bindings
registerDynamicEngineDefs<gridfire::GraphEngine, gridfire::DynamicEngine>(py_graph_engine_bindings);
registerDynamicEngineDefs<gridfire::engine::GraphEngine, gridfire::engine::DynamicEngine>(py_graph_engine_bindings);
}
void register_engine_view_bindings(const pybind11::module &m) {
auto py_defined_engine_view_bindings = py::class_<gridfire::DefinedEngineView, gridfire::DynamicEngine>(m, "DefinedEngineView");
auto py_defined_engine_view_bindings = py::class_<gridfire::engine::DefinedEngineView, gridfire::engine::DynamicEngine>(m, "DefinedEngineView");
py_defined_engine_view_bindings.def(py::init<std::vector<std::string>, gridfire::GraphEngine&>(),
py_defined_engine_view_bindings.def(py::init<std::vector<std::string>, gridfire::engine::GraphEngine&>(),
py::arg("peNames"),
py::arg("baseEngine"),
"Construct a defined engine view with a list of tracked reactions and a base engine."
);
py_defined_engine_view_bindings.def("getBaseEngine", &gridfire::DefinedEngineView::getBaseEngine,
py_defined_engine_view_bindings.def("getBaseEngine", &gridfire::engine::DefinedEngineView::getBaseEngine,
"Get the base engine associated with this defined engine view.");
registerDynamicEngineDefs<gridfire::DefinedEngineView, gridfire::DynamicEngine>(py_defined_engine_view_bindings);
registerDynamicEngineDefs<gridfire::engine::DefinedEngineView, gridfire::engine::DynamicEngine>(py_defined_engine_view_bindings);
auto py_file_defined_engine_view_bindings = py::class_<gridfire::FileDefinedEngineView, gridfire::DefinedEngineView>(m, "FileDefinedEngineView");
auto py_file_defined_engine_view_bindings = py::class_<gridfire::engine::FileDefinedEngineView, gridfire::engine::DefinedEngineView>(m, "FileDefinedEngineView");
py_file_defined_engine_view_bindings.def(
py::init<gridfire::GraphEngine&, const std::string&, const gridfire::io::NetworkFileParser&>(),
py::init<gridfire::engine::GraphEngine&, const std::string&, const gridfire::io::NetworkFileParser&>(),
py::arg("baseEngine"),
py::arg("fileName"),
py::arg("parser"),
"Construct a defined engine view from a file and a base engine."
);
py_file_defined_engine_view_bindings.def("getNetworkFile", &gridfire::FileDefinedEngineView::getNetworkFile,
py_file_defined_engine_view_bindings.def("getNetworkFile", &gridfire::engine::FileDefinedEngineView::getNetworkFile,
"Get the network file associated with this defined engine view."
);
py_file_defined_engine_view_bindings.def("getParser", &gridfire::FileDefinedEngineView::getParser,
py_file_defined_engine_view_bindings.def("getParser", &gridfire::engine::FileDefinedEngineView::getParser,
"Get the parser used for this defined engine view."
);
py_file_defined_engine_view_bindings.def("getBaseEngine", &gridfire::FileDefinedEngineView::getBaseEngine,
py_file_defined_engine_view_bindings.def("getBaseEngine", &gridfire::engine::FileDefinedEngineView::getBaseEngine,
"Get the base engine associated with this file defined engine view.");
registerDynamicEngineDefs<gridfire::FileDefinedEngineView, gridfire::DefinedEngineView>(py_file_defined_engine_view_bindings);
registerDynamicEngineDefs<gridfire::engine::FileDefinedEngineView, gridfire::engine::DefinedEngineView>(py_file_defined_engine_view_bindings);
auto py_priming_engine_view_bindings = py::class_<gridfire::NetworkPrimingEngineView, gridfire::DefinedEngineView>(m, "NetworkPrimingEngineView");
py_priming_engine_view_bindings.def(py::init<const std::string&, gridfire::GraphEngine&>(),
auto py_priming_engine_view_bindings = py::class_<gridfire::engine::NetworkPrimingEngineView, gridfire::engine::DefinedEngineView>(m, "NetworkPrimingEngineView");
py_priming_engine_view_bindings.def(py::init<const std::string&, gridfire::engine::GraphEngine&>(),
py::arg("primingSymbol"),
py::arg("baseEngine"),
"Construct a priming engine view with a priming symbol and a base engine.");
py_priming_engine_view_bindings.def(py::init<const fourdst::atomic::Species&, gridfire::GraphEngine&>(),
py_priming_engine_view_bindings.def(py::init<const fourdst::atomic::Species&, gridfire::engine::GraphEngine&>(),
py::arg("primingSpecies"),
py::arg("baseEngine"),
"Construct a priming engine view with a priming species and a base engine.");
py_priming_engine_view_bindings.def("getBaseEngine", &gridfire::NetworkPrimingEngineView::getBaseEngine,
py_priming_engine_view_bindings.def("getBaseEngine", &gridfire::engine::NetworkPrimingEngineView::getBaseEngine,
"Get the base engine associated with this priming engine view.");
registerDynamicEngineDefs<gridfire::NetworkPrimingEngineView, gridfire::DefinedEngineView>(py_priming_engine_view_bindings);
registerDynamicEngineDefs<gridfire::engine::NetworkPrimingEngineView, gridfire::engine::DefinedEngineView>(py_priming_engine_view_bindings);
auto py_adaptive_engine_view_bindings = py::class_<gridfire::AdaptiveEngineView, gridfire::DynamicEngine>(m, "AdaptiveEngineView");
py_adaptive_engine_view_bindings.def(py::init<gridfire::DynamicEngine&>(),
auto py_adaptive_engine_view_bindings = py::class_<gridfire::engine::AdaptiveEngineView, gridfire::engine::DynamicEngine>(m, "AdaptiveEngineView");
py_adaptive_engine_view_bindings.def(py::init<gridfire::engine::DynamicEngine&>(),
py::arg("baseEngine"),
"Construct an adaptive engine view with a base engine.");
py_adaptive_engine_view_bindings.def("getBaseEngine",
&gridfire::AdaptiveEngineView::getBaseEngine,
&gridfire::engine::AdaptiveEngineView::getBaseEngine,
"Get the base engine associated with this adaptive engine view."
);
registerDynamicEngineDefs<gridfire::AdaptiveEngineView, gridfire::DynamicEngine>(py_adaptive_engine_view_bindings);
registerDynamicEngineDefs<gridfire::engine::AdaptiveEngineView, gridfire::engine::DynamicEngine>(py_adaptive_engine_view_bindings);
auto py_qse_cache_config = py::class_<gridfire::QSECacheConfig>(m, "QSECacheConfig");
auto py_qse_cache_key = py::class_<gridfire::QSECacheKey>(m, "QSECacheKey");
py_qse_cache_key.def(py::init<double, double, const std::vector<double>&>(),
py::arg("T9"),
py::arg("rho"),
py::arg("Y")
);
py_qse_cache_key.def("hash", &gridfire::QSECacheKey::hash,
"Get the pre-computed hash value of the key");
py_qse_cache_key.def_static("bin", &gridfire::QSECacheKey::bin,
py::arg("value"),
py::arg("tol"),
"bin a value based on a tolerance");
py_qse_cache_key.def("__eq__", &gridfire::QSECacheKey::operator==,
py::arg("other"),
"Check if two QSECacheKeys are equal");
auto py_multiscale_engine_view_bindings = py::class_<gridfire::MultiscalePartitioningEngineView, gridfire::DynamicEngine>(m, "MultiscalePartitioningEngineView");
py_multiscale_engine_view_bindings.def(py::init<gridfire::GraphEngine&>(),
auto py_multiscale_engine_view_bindings = py::class_<gridfire::engine::MultiscalePartitioningEngineView, gridfire::engine::DynamicEngine>(m, "MultiscalePartitioningEngineView");
py_multiscale_engine_view_bindings.def(py::init<gridfire::engine::GraphEngine&>(),
py::arg("baseEngine"),
"Construct a multiscale partitioning engine view with a base engine."
);
py_multiscale_engine_view_bindings.def("getBaseEngine",
&gridfire::MultiscalePartitioningEngineView::getBaseEngine,
&gridfire::engine::MultiscalePartitioningEngineView::getBaseEngine,
"Get the base engine associated with this multiscale partitioning engine view."
);
py_multiscale_engine_view_bindings.def("analyzeTimescalePoolConnectivity",
&gridfire::MultiscalePartitioningEngineView::analyzeTimescalePoolConnectivity,
py::arg("timescale_pools"),
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
"Analyze the connectivity of timescale pools in the network."
);
py_multiscale_engine_view_bindings.def("partitionNetwork",
py::overload_cast<const fourdst::composition::Composition&, double, double>(&gridfire::MultiscalePartitioningEngineView::partitionNetwork),
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
&gridfire::engine::MultiscalePartitioningEngineView::partitionNetwork,
py::arg("netIn"),
"Partition the network based on species timescales and connectivity.");
py_multiscale_engine_view_bindings.def("partitionNetwork",
py::overload_cast<const gridfire::NetIn&>(&gridfire::MultiscalePartitioningEngineView::partitionNetwork),
py::overload_cast<const gridfire::NetIn&>(&gridfire::engine::MultiscalePartitioningEngineView::partitionNetwork),
py::arg("netIn"),
"Partition the network based on a NetIn object."
);
py_multiscale_engine_view_bindings.def("exportToDot",
&gridfire::MultiscalePartitioningEngineView::exportToDot,
&gridfire::engine::MultiscalePartitioningEngineView::exportToDot,
py::arg("filename"),
py::arg("comp"),
py::arg("T9"),
@@ -566,26 +638,37 @@ void register_engine_view_bindings(const pybind11::module &m) {
"Export the network to a DOT file for visualization."
);
py_multiscale_engine_view_bindings.def("getFastSpecies",
&gridfire::MultiscalePartitioningEngineView::getFastSpecies,
&gridfire::engine::MultiscalePartitioningEngineView::getFastSpecies,
"Get the list of fast species in the network."
);
py_multiscale_engine_view_bindings.def("getDynamicSpecies",
&gridfire::MultiscalePartitioningEngineView::getDynamicSpecies,
&gridfire::engine::MultiscalePartitioningEngineView::getDynamicSpecies,
"Get the list of dynamic species in the network."
);
py_multiscale_engine_view_bindings.def("equilibrateNetwork",
py::overload_cast<const fourdst::composition::Composition&, double, double>(&gridfire::MultiscalePartitioningEngineView::equilibrateNetwork),
py_multiscale_engine_view_bindings.def("involvesSpecies",
&gridfire::engine::MultiscalePartitioningEngineView::involvesSpecies,
py::arg("species"),
"Check if a given species is involved in the network (in either the algebraic or dynamic set)."
);
py_multiscale_engine_view_bindings.def("involvesSpeciesInQSE",
&gridfire::engine::MultiscalePartitioningEngineView::involvesSpeciesInQSE,
py::arg("species"),
"Check if a given species is involved in the network's algebraic set."
);
py_multiscale_engine_view_bindings.def("involvesSpeciesInDynamic",
&gridfire::engine::MultiscalePartitioningEngineView::involvesSpeciesInDynamic,
py::arg("species"),
"Check if a given species is involved in the network's dynamic set."
);
py_multiscale_engine_view_bindings.def("getNormalizedEquilibratedComposition",
&gridfire::engine::MultiscalePartitioningEngineView::getNormalizedEquilibratedComposition,
py::arg("comp"),
py::arg("T9"),
py::arg("rho"),
"Equilibrate the network based on species abundances and conditions.");
py_multiscale_engine_view_bindings.def("equilibrateNetwork",
py::overload_cast<const gridfire::NetIn&>(&gridfire::MultiscalePartitioningEngineView::equilibrateNetwork),
py::arg("netIn"),
"Equilibrate the network based on a NetIn object."
"Get the normalized equilibrated composition for the algebraic species."
);
registerDynamicEngineDefs<gridfire::MultiscalePartitioningEngineView, gridfire::DynamicEngine>(
registerDynamicEngineDefs<gridfire::engine::MultiscalePartitioningEngineView, gridfire::engine::DynamicEngine>(
py_multiscale_engine_view_bindings
);

View File

@@ -20,7 +20,9 @@ void register_engine_construction_bindings(pybind11::module &m);
void register_engine_priming_bindings(pybind11::module &m);
void register_engine_type_bindings(pybind11::module &m);
void register_engine_building_type_bindings(pybind11::module &m);
void register_engine_reporting_type_bindings(pybind11::module &m);
void register_engine_building_type_bindings(const pybind11::module &m);
void register_engine_reporting_type_bindings(const pybind11::module &m);
void register_engine_types_bindings(const pybind11::module &m);
void register_jacobian_type_bindings(pybind11::module &m);

View File

@@ -33,10 +33,14 @@ const std::vector<fourdst::atomic::Species>& PyEngine::getNetworkSpecies() const
py::pybind11_fail("Tried to call pure virtual function \"DynamicEngine::getNetworkSpecies\"");
}
std::expected<gridfire::StepDerivatives<double>, gridfire::expectations::StaleEngineError> PyEngine::calculateRHSAndEnergy(const fourdst::composition::Composition &comp, double T9, double rho) const {
std::expected<gridfire::engine::StepDerivatives<double>, gridfire::engine::EngineStatus> PyEngine::calculateRHSAndEnergy(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const {
PYBIND11_OVERRIDE_PURE(
PYBIND11_TYPE(std::expected<gridfire::StepDerivatives<double>, gridfire::expectations::StaleEngineError>),
gridfire::Engine,
PYBIND11_TYPE(std::expected<gridfire::engine::StepDerivatives<double>, gridfire::engine::EngineStatus>),
gridfire::engine::Engine,
calculateRHSAndEnergy,
comp, T9, rho
);
@@ -65,19 +69,29 @@ const std::vector<fourdst::atomic::Species>& PyDynamicEngine::getNetworkSpecies(
py::pybind11_fail("Tried to call pure virtual function \"DynamicEngine::getNetworkSpecies\"");
}
std::expected<gridfire::StepDerivatives<double>, gridfire::expectations::StaleEngineError> PyDynamicEngine::calculateRHSAndEnergy(const fourdst::composition::Composition &comp, double T9, double rho) const {
std::expected<gridfire::engine::StepDerivatives<double>, gridfire::engine::EngineStatus> PyDynamicEngine::calculateRHSAndEnergy(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const {
PYBIND11_OVERRIDE_PURE(
PYBIND11_TYPE(std::expected<gridfire::StepDerivatives<double>, gridfire::expectations::StaleEngineError>),
gridfire::Engine,
PYBIND11_TYPE(std::expected<gridfire::engine::StepDerivatives<double>, gridfire::engine::EngineStatus>),
gridfire::engine::DynamicEngine,
calculateRHSAndEnergy,
comp, T9, rho
);
}
void PyDynamicEngine::generateJacobianMatrix(const fourdst::composition::Composition& comp, double T9, double rho) const {
gridfire::engine::NetworkJacobian PyDynamicEngine::generateJacobianMatrix(
const fourdst::composition::CompositionAbstract& comp,
double T9,
double rho
) const {
PYBIND11_OVERRIDE_PURE(
void,
gridfire::DynamicEngine,
gridfire::engine::NetworkJacobian,
gridfire::engine::DynamicEngine,
generateJacobianMatrix,
comp,
T9,
@@ -85,15 +99,15 @@ void PyDynamicEngine::generateJacobianMatrix(const fourdst::composition::Composi
);
}
void PyDynamicEngine::generateJacobianMatrix(
const fourdst::composition::Composition &comp,
gridfire::engine::NetworkJacobian PyDynamicEngine::generateJacobianMatrix(
const fourdst::composition::CompositionAbstract &comp,
const double T9,
const double rho,
const std::vector<fourdst::atomic::Species> &activeSpecies
) const {
PYBIND11_OVERRIDE_PURE(
void,
gridfire::DynamicEngine,
gridfire::engine::NetworkJacobian,
gridfire::engine::DynamicEngine,
generateJacobianMatrix,
comp,
T9,
@@ -102,10 +116,15 @@ void PyDynamicEngine::generateJacobianMatrix(
);
}
void PyDynamicEngine::generateJacobianMatrix(const fourdst::composition::Composition &comp, double T9, double rho, const gridfire::SparsityPattern &sparsityPattern) const {
gridfire::engine::NetworkJacobian PyDynamicEngine::generateJacobianMatrix(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const gridfire::engine::SparsityPattern &sparsityPattern
) const {
PYBIND11_OVERRIDE_PURE(
void,
gridfire::DynamicEngine,
gridfire::engine::NetworkJacobian,
gridfire::engine::DynamicEngine,
generateJacobianMatrix,
comp,
T9,
@@ -114,38 +133,36 @@ void PyDynamicEngine::generateJacobianMatrix(const fourdst::composition::Composi
);
}
double PyDynamicEngine::getJacobianMatrixEntry(const fourdst::atomic::Species& rowSpecies, const fourdst::atomic::Species& colSpecies) const {
PYBIND11_OVERRIDE_PURE(
double,
gridfire::DynamicEngine,
getJacobianMatrixEntry,
rowSpecies,
colSpecies
);
}
void PyDynamicEngine::generateStoichiometryMatrix() {
PYBIND11_OVERRIDE_PURE(
void,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
generateStoichiometryMatrix
);
}
int PyDynamicEngine::getStoichiometryMatrixEntry(const fourdst::atomic::Species& species, const gridfire::reaction::Reaction& reaction) const {
int PyDynamicEngine::getStoichiometryMatrixEntry(
const fourdst::atomic::Species& species,
const gridfire::reaction::Reaction& reaction
) const {
PYBIND11_OVERRIDE_PURE(
int,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
getStoichiometryMatrixEntry,
species,
reaction
);
}
double PyDynamicEngine::calculateMolarReactionFlow(const gridfire::reaction::Reaction &reaction, const fourdst::composition::Composition &comp, double T9, double rho) const {
double PyDynamicEngine::calculateMolarReactionFlow(
const gridfire::reaction::Reaction &reaction,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const {
PYBIND11_OVERRIDE_PURE(
double,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
calculateMolarReactionFlow,
reaction,
comp,
@@ -157,7 +174,7 @@ double PyDynamicEngine::calculateMolarReactionFlow(const gridfire::reaction::Rea
const gridfire::reaction::ReactionSet& PyDynamicEngine::getNetworkReactions() const {
PYBIND11_OVERRIDE_PURE(
const gridfire::reaction::ReactionSet&,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
getNetworkReactions
);
}
@@ -165,16 +182,20 @@ const gridfire::reaction::ReactionSet& PyDynamicEngine::getNetworkReactions() co
void PyDynamicEngine::setNetworkReactions(const gridfire::reaction::ReactionSet& reactions) {
PYBIND11_OVERRIDE_PURE(
void,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
setNetworkReactions,
reactions
);
}
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::expectations::StaleEngineError> PyDynamicEngine::getSpeciesTimescales(const fourdst::composition::Composition &comp, double T9, double rho) const {
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::engine::EngineStatus> PyDynamicEngine::getSpeciesTimescales(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const {
PYBIND11_OVERRIDE_PURE(
PYBIND11_TYPE(std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::expectations::StaleEngineError>),
gridfire::DynamicEngine,
PYBIND11_TYPE(std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::engine::EngineStatus>),
gridfire::engine::DynamicEngine,
getSpeciesTimescales,
comp,
T9,
@@ -182,10 +203,14 @@ std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::ex
);
}
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::expectations::StaleEngineError> PyDynamicEngine::getSpeciesDestructionTimescales(const fourdst::composition::Composition &comp, double T9, double rho) const {
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::engine::EngineStatus> PyDynamicEngine::getSpeciesDestructionTimescales(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const {
PYBIND11_OVERRIDE_PURE(
PYBIND11_TYPE(std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::expectations::StaleEngineError>),
gridfire::DynamicEngine,
PYBIND11_TYPE(std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::engine::EngineStatus>),
gridfire::engine::DynamicEngine,
getSpeciesDestructionTimescales,
comp, T9, rho
);
@@ -194,7 +219,7 @@ std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::ex
fourdst::composition::Composition PyDynamicEngine::update(const gridfire::NetIn &netIn) {
PYBIND11_OVERRIDE_PURE(
fourdst::composition::Composition,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
update,
netIn
);
@@ -203,7 +228,7 @@ fourdst::composition::Composition PyDynamicEngine::update(const gridfire::NetIn
bool PyDynamicEngine::isStale(const gridfire::NetIn &netIn) {
PYBIND11_OVERRIDE_PURE(
bool,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
isStale,
netIn
);
@@ -212,7 +237,7 @@ bool PyDynamicEngine::isStale(const gridfire::NetIn &netIn) {
void PyDynamicEngine::setScreeningModel(gridfire::screening::ScreeningType model) {
PYBIND11_OVERRIDE_PURE(
void,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
setScreeningModel,
model
);
@@ -221,7 +246,7 @@ void PyDynamicEngine::setScreeningModel(gridfire::screening::ScreeningType model
gridfire::screening::ScreeningType PyDynamicEngine::getScreeningModel() const {
PYBIND11_OVERRIDE_PURE(
gridfire::screening::ScreeningType,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
getScreeningModel
);
}
@@ -229,7 +254,7 @@ gridfire::screening::ScreeningType PyDynamicEngine::getScreeningModel() const {
size_t PyDynamicEngine::getSpeciesIndex(const fourdst::atomic::Species &species) const {
PYBIND11_OVERRIDE_PURE(
int,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
getSpeciesIndex,
species
);
@@ -238,28 +263,28 @@ size_t PyDynamicEngine::getSpeciesIndex(const fourdst::atomic::Species &species)
std::vector<double> PyDynamicEngine::mapNetInToMolarAbundanceVector(const gridfire::NetIn &netIn) const {
PYBIND11_OVERRIDE_PURE(
std::vector<double>,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
mapNetInToMolarAbundanceVector,
netIn
);
}
gridfire::PrimingReport PyDynamicEngine::primeEngine(const gridfire::NetIn &netIn) {
gridfire::engine::PrimingReport PyDynamicEngine::primeEngine(const gridfire::NetIn &netIn) {
PYBIND11_OVERRIDE_PURE(
gridfire::PrimingReport,
gridfire::DynamicEngine,
gridfire::engine::PrimingReport,
gridfire::engine::DynamicEngine,
primeEngine,
netIn
);
}
gridfire::EnergyDerivatives PyDynamicEngine::calculateEpsDerivatives(
const fourdst::composition::Composition &comp,
gridfire::engine::EnergyDerivatives PyDynamicEngine::calculateEpsDerivatives(
const fourdst::composition::CompositionAbstract &comp,
const double T9,
const double rho) const {
PYBIND11_OVERRIDE_PURE(
gridfire::EnergyDerivatives,
gridfire::DynamicEngine,
gridfire::engine::EnergyDerivatives,
gridfire::engine::DynamicEngine,
calculateEpsDerivatives,
comp,
T9,
@@ -268,28 +293,41 @@ gridfire::EnergyDerivatives PyDynamicEngine::calculateEpsDerivatives(
}
fourdst::composition::Composition PyDynamicEngine::collectComposition(
fourdst::composition::Composition &comp
const fourdst::composition::CompositionAbstract &comp,
const double T9,
const double rho
) const {
PYBIND11_OVERRIDE_PURE(
fourdst::composition::Composition,
gridfire::DynamicEngine,
gridfire::engine::DynamicEngine,
collectComposition,
comp
comp,
T9,
rho
);
}
const gridfire::Engine& PyEngineView::getBaseEngine() const {
gridfire::engine::SpeciesStatus PyDynamicEngine::getSpeciesStatus(const fourdst::atomic::Species &species) const {
PYBIND11_OVERRIDE_PURE(
const gridfire::Engine&,
gridfire::EngineView<gridfire::Engine>,
gridfire::engine::SpeciesStatus,
gridfire::engine::DynamicEngine,
getSpeciesStatus,
species
);
}
const gridfire::engine::Engine& PyEngineView::getBaseEngine() const {
PYBIND11_OVERRIDE_PURE(
const gridfire::engine::Engine&,
gridfire::engine::EngineView<gridfire::engine::Engine>,
getBaseEngine
);
}
const gridfire::DynamicEngine& PyDynamicEngineView::getBaseEngine() const {
const gridfire::engine::DynamicEngine& PyDynamicEngineView::getBaseEngine() const {
PYBIND11_OVERRIDE_PURE(
const gridfire::DynamicEngine&,
gridfire::EngineView<gridfire::DynamicEngine>,
const gridfire::engine::DynamicEngine&,
gridfire::engine::EngineView<gridfire::engine::DynamicEngine>,
getBaseEngine
);
}

View File

@@ -1,7 +1,6 @@
#pragma once
#include "gridfire/engine/engine.h"
#include "gridfire/expectations/expected_engine.h"
#include "fourdst/atomic/atomicSpecies.h"
@@ -9,11 +8,11 @@
#include <expected>
class PyEngine final : public gridfire::Engine {
class PyEngine final : public gridfire::engine::Engine {
public:
const std::vector<fourdst::atomic::Species>& getNetworkSpecies() const override;
std::expected<gridfire::StepDerivatives<double>,gridfire::expectations::StaleEngineError> calculateRHSAndEnergy(
std::expected<gridfire::engine::StepDerivatives<double>, gridfire::engine::EngineStatus> calculateRHSAndEnergy(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
@@ -22,39 +21,34 @@ private:
mutable std::vector<fourdst::atomic::Species> m_species_cache;
};
class PyDynamicEngine final : public gridfire::DynamicEngine {
class PyDynamicEngine final : public gridfire::engine::DynamicEngine {
public:
const std::vector<fourdst::atomic::Species>& getNetworkSpecies() const override;
std::expected<gridfire::StepDerivatives<double>, gridfire::expectations::StaleEngineError> calculateRHSAndEnergy(
std::expected<gridfire::engine::StepDerivatives<double>, gridfire::engine::EngineStatus> calculateRHSAndEnergy(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
gridfire::engine::NetworkJacobian generateJacobianMatrix(
const fourdst::composition::CompositionAbstract& comp,
double T9,
double rho
) const override;
void generateJacobianMatrix(
gridfire::engine::NetworkJacobian generateJacobianMatrix(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species> &activeSpecies
) const override;
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
gridfire::engine::NetworkJacobian generateJacobianMatrix(
const fourdst::composition::CompositionAbstract& comp,
double T9,
double rho,
const gridfire::SparsityPattern &sparsityPattern
) const override;
double getJacobianMatrixEntry(
const fourdst::atomic::Species& rowSpecies,
const fourdst::atomic::Species& colSpecies
const gridfire::engine::SparsityPattern &sparsityPattern
) const override;
void generateStoichiometryMatrix() override;
@@ -77,14 +71,14 @@ public:
const gridfire::reaction::ReactionSet& reactions
) override;
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::expectations::StaleEngineError> getSpeciesTimescales(
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::engine::EngineStatus> getSpeciesTimescales(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition &comp,
std::expected<std::unordered_map<fourdst::atomic::Species, double>, gridfire::engine::EngineStatus> getSpeciesDestructionTimescales(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -111,38 +105,44 @@ public:
const gridfire::NetIn &netIn
) const override;
gridfire::PrimingReport primeEngine(
gridfire::engine::PrimingReport primeEngine(
const gridfire::NetIn &netIn
) override;
gridfire::BuildDepthType getDepth() const override {
gridfire::engine::BuildDepthType getDepth() const override {
throw std::logic_error("Network depth not supported by this engine.");
}
void rebuild(
const fourdst::composition::CompositionAbstract &comp,
gridfire::BuildDepthType depth
gridfire::engine::BuildDepthType depth
) override {
throw std::logic_error("Setting network depth not supported by this engine.");
}
[[nodiscard]] gridfire::EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition &comp,
[[nodiscard]] gridfire::engine::EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
fourdst::composition::Composition collectComposition(
fourdst::composition::Composition &comp
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
gridfire::engine::SpeciesStatus getSpeciesStatus(
const fourdst::atomic::Species &species
) const override;
private:
mutable std::vector<fourdst::atomic::Species> m_species_cache;
};
class PyEngineView final : public gridfire::EngineView<gridfire::Engine> {
[[nodiscard]] const gridfire::Engine& getBaseEngine() const override;
class PyEngineView final : public gridfire::engine::EngineView<gridfire::engine::Engine> {
[[nodiscard]] const gridfire::engine::Engine& getBaseEngine() const override;
};
class PyDynamicEngineView final : public gridfire::EngineView<gridfire::DynamicEngine> {
[[nodiscard]] const gridfire::DynamicEngine& getBaseEngine() const override;
class PyDynamicEngineView final : public gridfire::engine::EngineView<gridfire::engine::DynamicEngine> {
[[nodiscard]] const gridfire::engine::DynamicEngine& getBaseEngine() const override;
};

View File

@@ -7,48 +7,41 @@ namespace py = pybind11;
#include "gridfire/exceptions/exceptions.h"
void register_exception_bindings(const py::module &m) {
py::register_exception<gridfire::exceptions::EngineError>(m, "GridFireEngineError");
py::register_exception<gridfire::exceptions::GridFireError>(m, "GridFireError");
// TODO: Make it so that we can grab the stale state in python
// m.attr("StaleEngineTrigger") = py::register_exception<gridfire::exceptions::StaleEngineTrigger>(m, "StaleEngineTrigger", m.attr("GridFireEngineError"));
m.attr("StaleEngineError") = py::register_exception<gridfire::exceptions::StaleEngineError>(m, "StaleEngineError", m.attr("GridFireEngineError"));
m.attr("FailedToPartitionEngineError") = py::register_exception<gridfire::exceptions::FailedToPartitionEngineError>(m, "FailedToPartitionEngineError", m.attr("GridFireEngineError"));
m.attr("NetworkResizedError") = py::register_exception<gridfire::exceptions::NetworkResizedError>(m, "NetworkResizedError", m.attr("GridFireEngineError"));
m.attr("UnableToSetNetworkReactionsError") = py::register_exception<gridfire::exceptions::UnableToSetNetworkReactionsError>(m, "UnableToSetNetworkReactionsError", m.attr("GridFireEngineError"));
py::register_exception<gridfire::exceptions::DebugException>(m, "DebugException", m.attr("GridFireError"));
py::class_<gridfire::exceptions::StaleEngineTrigger::state>(m, "StaleEngineState")
.def(py::init<>())
.def_readwrite("T9", &gridfire::exceptions::StaleEngineTrigger::state::m_T9)
.def_readwrite("rho", &gridfire::exceptions::StaleEngineTrigger::state::m_rho)
.def_readwrite("Y", &gridfire::exceptions::StaleEngineTrigger::state::m_Y)
.def_readwrite("t", &gridfire::exceptions::StaleEngineTrigger::state::m_t)
.def_readwrite("total_steps", &gridfire::exceptions::StaleEngineTrigger::state::m_total_steps)
.def_readwrite("eps_nuc", &gridfire::exceptions::StaleEngineTrigger::state::m_eps_nuc);
py::register_exception<gridfire::exceptions::EngineError>(m, "EngineError", m.attr("GridFireError"));
py::class_<gridfire::exceptions::StaleEngineTrigger>(m, "StaleEngineTrigger")
.def(py::init<const gridfire::exceptions::StaleEngineTrigger::state &>())
.def("getState", &gridfire::exceptions::StaleEngineTrigger::getState)
.def("numSpecies", &gridfire::exceptions::StaleEngineTrigger::numSpecies)
.def("totalSteps", &gridfire::exceptions::StaleEngineTrigger::totalSteps)
.def("energy", &gridfire::exceptions::StaleEngineTrigger::energy)
.def("getMolarAbundance", &gridfire::exceptions::StaleEngineTrigger::getMolarAbundance)
.def("temperature", &gridfire::exceptions::StaleEngineTrigger::temperature)
.def("density", &gridfire::exceptions::StaleEngineTrigger::density)
.def("__repr__", [&](const gridfire::exceptions::StaleEngineTrigger& self) {
return self.what();
});
py::register_exception<gridfire::exceptions::FailedToPartitionEngineError>(m, "FailedToPartitionEngineError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::NetworkResizedError>(m, "NetworkResizedError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::UnableToSetNetworkReactionsError>(m, "UnableToSetNetworkReactionsError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::BadCollectionError>(m, "BadCollectionError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::InvalidQSESolutionError>(m, "InvalidQSESolutionError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::BadRHSEngineError>(m, "BadRHSEngineError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::FailedToPartitionEngineError>(m, "FailedToPartitionEngineError", m.attr("GridFireEngineError"));
py::register_exception<gridfire::exceptions::NetworkResizedError>(m, "NetworkResizedError", m.attr("GridFireEngineError"));
py::register_exception<gridfire::exceptions::UnableToSetNetworkReactionsError>(m, "UnableToSetNetworkReactionsError", m.attr("GridFireEngineError"));
py::register_exception<gridfire::exceptions::BadCollectionError>(m, "BadCollectionError", m.attr("GridFireEngineError"));
py::register_exception<gridfire::exceptions::JacobianError>(m, "JacobianError", m.attr("GridFireEngineError"));
py::register_exception<gridfire::exceptions::JacobianError>(m, "JacobianError", m.attr("EngineError"));
py::register_exception<gridfire::exceptions::StaleJacobianError>(m, "StaleJacobianError", m.attr("JacobianError"));
py::register_exception<gridfire::exceptions::UninitializedJacobianError>(m, "UninitializedJacobianError", m.attr("JacobianError"));
py::register_exception<gridfire::exceptions::UnknownJacobianError>(m, "UnknownJacobianError", m.attr("JacobianError"));
py::register_exception<gridfire::exceptions::UtilityError>(m, "UtilityError");
py::register_exception<gridfire::exceptions::UtilityError>(m, "UtilityError", m.attr("GridFireError"));
py::register_exception<gridfire::exceptions::HashingError>(m, "HashingError", m.attr("UtilityError"));
py::register_exception<gridfire::exceptions::PolicyError>(m, "PolicyError", m.attr("GridFireError"));
py::register_exception<gridfire::exceptions::MissingBaseReactionError>(m, "MissingBaseReactionError", m.attr("PolicyError"));
py::register_exception<gridfire::exceptions::MissingSeedSpeciesError>(m, "MissingSeedSpeciesError", m.attr("PolicyError"));
py::register_exception<gridfire::exceptions::MissingKeyReactionError>(m, "MissingKeyReactionError", m.attr("PolicyError"));
py::register_exception<gridfire::exceptions::ReactionError>(m, "ReactionError", m.attr("GridFireError"));
py::register_exception<gridfire::exceptions::ReactionParsingError>(m, "ReactionParsingError", m.attr("ReactionError"));
py::register_exception<gridfire::exceptions::SolverError>(m, "SolverError", m.attr("GridFireError"));
py::register_exception<gridfire::exceptions::SingularJacobianError>(m, "SingularJacobianError", m.attr("SolverError"));
py::register_exception<gridfire::exceptions::IllConditionedJacobianError>(m, "IllConditionedJacobianError", m.attr("SolverError"));
py::register_exception<gridfire::exceptions::SUNDIALSError>(m, "SUNDIALSError", m.attr("SolverError"));
py::register_exception<gridfire::exceptions::CVODESolverFailureError>(m, "CVODESolverFailureError", m.attr("SUNDIALSError"));
py::register_exception<gridfire::exceptions::KINSolSolverFailureError>(m, "KINSolSolverFailureError", m.attr("SUNDIALSError"));
}

View File

@@ -1,43 +0,0 @@
#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 "bindings.h"
namespace py = pybind11;
#include "gridfire/expectations/expectations.h"
void register_expectation_bindings(const py::module &m) {
py::enum_<gridfire::expectations::EngineErrorTypes>(m, "EngineErrorTypes")
.value("FAILURE", gridfire::expectations::EngineErrorTypes::FAILURE)
.value("INDEX", gridfire::expectations::EngineErrorTypes::INDEX)
.value("STALE", gridfire::expectations::EngineErrorTypes::STALE)
.export_values();
py::enum_<gridfire::expectations::StaleEngineErrorTypes>(m, "StaleEngineErrorTypes")
.value("SYSTEM_RESIZED", gridfire::expectations::StaleEngineErrorTypes::SYSTEM_RESIZED)
.export_values();
// Bind the base class
py::class_<gridfire::expectations::EngineError>(m, "EngineError")
.def_readonly("message", &gridfire::expectations::EngineError::m_message)
.def_readonly("type", &gridfire::expectations::EngineError::type)
.def("__str__", [](const gridfire::expectations::EngineError &e) {return e.m_message;});
// Bind the EngineIndexError, specifying EngineError as the base
py::class_<gridfire::expectations::EngineIndexError, gridfire::expectations::EngineError>(m, "EngineIndexError")
.def(py::init<int>(), py::arg("index"))
.def_readonly("index", &gridfire::expectations::EngineIndexError::m_index)
.def("__str__", [](const gridfire::expectations::EngineIndexError &e) {
return e.m_message + " at index " + std::to_string(e.m_index);
});
// Bind the StaleEngineError, specifying EngineError as the base
py::class_<gridfire::expectations::StaleEngineError, gridfire::expectations::EngineError>(m, "StaleEngineError")
.def(py::init<gridfire::expectations::StaleEngineErrorTypes>(), py::arg("stale_type"))
.def_readonly("stale_type", &gridfire::expectations::StaleEngineError::staleType)
.def("__str__", [](const gridfire::expectations::StaleEngineError &e) {
return static_cast<std::string>(e);
});
}

View File

@@ -1,5 +0,0 @@
#pragma once
#include <pybind11/pybind11.h>
void register_expectation_bindings(const pybind11::module &m);

View File

@@ -0,0 +1,20 @@
from ._gridfire import *
import sys
from ._gridfire import type, utils, engine, solver, exceptions, partition, reaction, screening, io, policy
sys.modules['gridfire.type'] = type
sys.modules['gridfire.utils'] = utils
sys.modules['gridfire.engine'] = engine
sys.modules['gridfire.solver'] = solver
sys.modules['gridfire.exceptions'] = exceptions
sys.modules['gridfire.partition'] = partition
sys.modules['gridfire.reaction'] = reaction
sys.modules['gridfire.screening'] = screening
sys.modules['gridfire.policy'] = policy
sys.modules['gridfire.io'] = io
__all__ = ['type', 'utils', 'engine', 'solver', 'exceptions', 'partition', 'reaction', 'screening', 'io', 'policy']
__version__ = "v0.7.0_alpha_2025_10_25"

View File

@@ -19,9 +19,4 @@ auto register_io_bindings(const py::module &m) -> void {
.def("parse", &gridfire::io::SimpleReactionListFileParser::parse,
py::arg("filename"),
"Parse a simple reaction list file and return a ParsedNetworkData object.");
// py::class_<gridfire::io::MESANetworkFileParser, gridfire::io::NetworkFileParser>(m, "MESANetworkFileParser")
// .def("parse", &gridfire::io::MESANetworkFileParser::parse,
// py::arg("filename"),
// "Parse a MESA network file and return a ParsedNetworkData object.");
}

View File

@@ -1,10 +1,10 @@
subdir('types')
subdir('utils')
subdir('expectations')
subdir('exceptions')
subdir('io')
subdir('partition')
subdir('reaction')
subdir('screening')
subdir('engine')
subdir('policy')
subdir('solver')

View File

@@ -0,0 +1,233 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include <memory>
#include "bindings.h"
#include "trampoline/py_policy.h"
#include "gridfire/policy/policy.h"
PYBIND11_DECLARE_HOLDER_TYPE(T, std::unique_ptr<T>, true) // Declare unique_ptr as a holder type for pybind11
namespace py = pybind11;
namespace {
template <typename T>
concept IsReactionChainPolicy = std::is_base_of_v<gridfire::policy::ReactionChainPolicy, T>;
template <typename T>
concept IsNetworkPolicy = std::is_base_of_v<gridfire::policy::NetworkPolicy, T>;
template<IsReactionChainPolicy T, IsReactionChainPolicy BaseT>
void registerReactionChainPolicyDefs(py::class_<T, BaseT>& pyClass) {
pyClass.def(
"get_reactions",
&T::get_reactions,
"Get the ReactionSet representing this reaction chain."
)
.def(
"contains",
py::overload_cast<const std::string&>(&T::contains, py::const_),
py::arg("id"),
"Check if the reaction chain contains a reaction with the given ID."
)
.def(
"contains",
py::overload_cast<const gridfire::reaction::Reaction&>(&T::contains, py::const_),
py::arg("reaction"),
"Check if the reaction chain contains the given reaction."
)
.def(
"name",
&T::name,
"Get the name of the reaction chain policy."
)
.def(
"hash",
&T::hash,
py::arg("seed"),
"Compute a hash value for the reaction chain policy."
)
.def(
"__eq__",
&T::operator==,
py::arg("other"),
"Check equality with another ReactionChainPolicy."
)
.def(
"__ne__",
&T::operator!=,
py::arg("other"),
"Check inequality with another ReactionChainPolicy."
)
.def("__hash__", [](const T &self) {
return self.hash(0);
}
)
.def("__repr__", [](const T &self) {
std::stringstream ss;
ss << self;
return ss.str();
});
}
template<IsNetworkPolicy T, IsNetworkPolicy BaseT>
void registerNetworkPolicyDefs(py::class_<T, BaseT> pyClass) {
pyClass.def(
"name",
&T::name,
"Get the name of the network policy."
)
.def(
"get_seed_species",
&T::get_seed_species,
"Get the set of seed species required by the network policy."
)
.def(
"get_seed_reactions",
&T::get_seed_reactions,
"Get the set of seed reactions required by the network policy."
)
.def(
"get_status",
&T::get_status,
"Get the current status of the network policy."
)
.def(
"get_engine_types_stack",
&T::get_engine_types_stack,
"Get the types of engines in the stack constructed by the network policy."
)
.def(
"construct",
&T::construct,
py::return_value_policy::reference,
"Construct the network according to the policy."
);
}
}
void register_policy_bindings(pybind11::module &m) {
register_reaction_chain_policy_bindings(m);
register_network_policy_bindings(m);
}
void register_reaction_chain_policy_bindings(pybind11::module &m) {
using namespace gridfire::policy;
py::class_<ReactionChainPolicy, PyReactionChainPolicy> py_reactionChainPolicy(m, "ReactionChainPolicy");
py::class_<MultiReactionChainPolicy, ReactionChainPolicy> py_multiChainPolicy(m, "MultiReactionChainPolicy");
py::class_<TemperatureDependentChainPolicy, ReactionChainPolicy> py_tempDepChainPolicy(m, "TemperatureDependentChainPolicy");
py::class_<ProtonProtonIChainPolicy, TemperatureDependentChainPolicy> py_ppI(m, "ProtonProtonIChainPolicy");
py_ppI.def(py::init<>());
py_ppI.def("name", &ProtonProtonIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<ProtonProtonIIChainPolicy, TemperatureDependentChainPolicy> py_ppII(m, "ProtonProtonIIChainPolicy");
py_ppII.def(py::init<>());
py_ppII.def("name", &ProtonProtonIIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<ProtonProtonIIIChainPolicy, TemperatureDependentChainPolicy> py_ppIII(m, "ProtonProtonIIIChainPolicy");
py_ppIII.def(py::init<>());
py_ppIII.def("name", &ProtonProtonIIIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<ProtonProtonChainPolicy, MultiReactionChainPolicy> py_ppChain(m, "ProtonProtonChainPolicy");
py_ppChain.def(py::init<>());
py_ppChain.def("name", &ProtonProtonChainPolicy::name, "Get the name of the reaction chain policy.");
registerReactionChainPolicyDefs(py_ppI);
registerReactionChainPolicyDefs(py_ppII);
registerReactionChainPolicyDefs(py_ppIII);
registerReactionChainPolicyDefs(py_ppChain);
py::class_<CNOIChainPolicy, TemperatureDependentChainPolicy> py_cnoI(m, "CNOIChainPolicy");
py_cnoI.def(py::init<>());
py_cnoI.def("name", &CNOIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<CNOIIChainPolicy, TemperatureDependentChainPolicy> py_cnoII(m, "CNOIIChainPolicy");
py_cnoII.def(py::init<>());
py_cnoII.def("name", &CNOIIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<CNOIIIChainPolicy, TemperatureDependentChainPolicy> py_cnoIII(m, "CNOIIIChainPolicy");
py_cnoIII.def(py::init<>());
py_cnoIII.def("name", &CNOIIIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<CNOIVChainPolicy, TemperatureDependentChainPolicy> py_cnoIV(m, "CNOIVChainPolicy");
py_cnoIV.def(py::init<>());
py_cnoIV.def("name", &CNOIVChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<CNOChainPolicy, MultiReactionChainPolicy> py_cnoChain(m, "CNOChainPolicy");
py_cnoChain.def(py::init<>());
py_cnoChain.def("name", &CNOChainPolicy::name, "Get the name of the reaction chain policy.");
registerReactionChainPolicyDefs(py_cnoI);
registerReactionChainPolicyDefs(py_cnoII);
registerReactionChainPolicyDefs(py_cnoIII);
registerReactionChainPolicyDefs(py_cnoIV);
registerReactionChainPolicyDefs(py_cnoChain);
py::class_<HotCNOIChainPolicy, TemperatureDependentChainPolicy> py_hotCNOI(m, "HotCNOIChainPolicy");
py_hotCNOI.def(py::init<>());
py_hotCNOI.def("name", &HotCNOIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<HotCNOIIChainPolicy, TemperatureDependentChainPolicy> py_hotCNOII(m, "HotCNOIIChainPolicy");
py_hotCNOII.def(py::init<>());
py_hotCNOII.def("name", &HotCNOIIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<HotCNOIIIChainPolicy, TemperatureDependentChainPolicy> py_hotCNOIII(m, "HotCNOIIIChainPolicy");
py_hotCNOIII.def(py::init<>());
py_hotCNOIII.def("name", &HotCNOIIIChainPolicy::name, "Get the name of the reaction chain policy.");
py::class_<HotCNOChainPolicy, MultiReactionChainPolicy> py_hotCNOChain(m, "HotCNOChainPolicy");
py_hotCNOChain.def(py::init<>());
py_hotCNOChain.def("name", &HotCNOChainPolicy::name, "Get the name of the reaction chain policy.");
registerReactionChainPolicyDefs(py_hotCNOI);
registerReactionChainPolicyDefs(py_hotCNOII);
registerReactionChainPolicyDefs(py_hotCNOIII);
registerReactionChainPolicyDefs(py_hotCNOChain);
py::class_<TripleAlphaChainPolicy, TemperatureDependentChainPolicy> py_tripleAlpha(m, "TripleAlphaChainPolicy");
py_tripleAlpha.def(py::init<>());
py_tripleAlpha.def("name", &TripleAlphaChainPolicy::name, "Get the name of the reaction chain policy.");
registerReactionChainPolicyDefs(py_tripleAlpha);
py::class_<MainSequenceReactionChainPolicy, MultiReactionChainPolicy> py_mainSeq(m, "MainSequenceReactionChainPolicy");
py_mainSeq.def(py::init<>());
py_mainSeq.def("name", &MainSequenceReactionChainPolicy::name, "Get the name of the reaction chain policy.");
registerReactionChainPolicyDefs(py_mainSeq);
}
void register_network_policy_bindings(pybind11::module &m) {
py::enum_<gridfire::policy::NetworkPolicyStatus>(m, "NetworkPolicyStatus")
.value("UNINITIALIZED", gridfire::policy::NetworkPolicyStatus::UNINITIALIZED)
.value("INITIALIZED_UNVERIFIED", gridfire::policy::NetworkPolicyStatus::INITIALIZED_UNVERIFIED)
.value("MISSING_KEY_REACTION", gridfire::policy::NetworkPolicyStatus::MISSING_KEY_REACTION)
.value("MISSING_KEY_SPECIES", gridfire::policy::NetworkPolicyStatus::MISSING_KEY_SPECIES)
.value("INITIALIZED_VERIFIED", gridfire::policy::NetworkPolicyStatus::INITIALIZED_VERIFIED)
.export_values();
py::class_<gridfire::policy::NetworkPolicy, PyNetworkPolicy> py_networkPolicy(m, "NetworkPolicy");
py::class_<gridfire::policy::MainSequencePolicy, gridfire::policy::NetworkPolicy> py_mainSeqPolicy(m, "MainSequencePolicy");
py_mainSeqPolicy.def(
py::init<const fourdst::composition::Composition&>(),
py::arg("composition"),
"Construct MainSequencePolicy from an existing composition."
);
py_mainSeqPolicy.def(
py::init<std::vector<fourdst::atomic::Species>, const std::vector<double>&>(),
py::arg("seed_species"),
py::arg("mass_fractions"),
"Construct MainSequencePolicy from seed species and mass fractions."
);
registerNetworkPolicyDefs(py_mainSeqPolicy);
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include <pybind11/pybind11.h>
void register_policy_bindings(pybind11::module& m);
void register_reaction_chain_policy_bindings(pybind11::module& m);
void register_network_policy_bindings(pybind11::module& m);

View File

@@ -1,4 +1,6 @@
# Define the library
subdir('trampoline')
bindings_sources = files('bindings.cpp')
bindings_headers = files('bindings.h')
@@ -8,7 +10,7 @@ dependencies = [
pybind11_dep,
]
shared_module('py_gf_expectations',
shared_module('py_gf_policy',
bindings_sources,
cpp_args: ['-fvisibility=default'],
install : true,

View File

@@ -0,0 +1,21 @@
gf_policy_trampoline_sources = files('py_policy.cpp')
gf_policy_trapoline_dependencies = [
gridfire_dep,
pybind11_dep,
python3_dep,
]
gf_policy_trampoline_lib = static_library(
'policy_trampolines',
gf_policy_trampoline_sources,
include_directories: include_directories('.'),
dependencies: gf_policy_trapoline_dependencies,
install: false,
)
gr_policy_trampoline_dep = declare_dependency(
link_with: gf_policy_trampoline_lib,
include_directories: ('.'),
dependencies: gf_policy_trapoline_dependencies,
)

View File

@@ -0,0 +1,149 @@
#include "py_policy.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "gridfire/reaction/reaction.h"
#include "gridfire/engine/engine.h"
#include "gridfire/policy/policy.h"
#include <string>
#include <set>
namespace py = pybind11;
std::string PyNetworkPolicy::name() const {
PYBIND11_OVERRIDE_PURE(
std::string,
gridfire::policy::NetworkPolicy,
name
);
}
const std::set<fourdst::atomic::Species>& PyNetworkPolicy::get_seed_species() const {
PYBIND11_OVERRIDE_PURE(
const std::set<fourdst::atomic::Species>&,
gridfire::policy::NetworkPolicy,
get_seed_species
);
}
const gridfire::reaction::ReactionSet& PyNetworkPolicy::get_seed_reactions() const {
PYBIND11_OVERRIDE_PURE(
const gridfire::reaction::ReactionSet&,
gridfire::policy::NetworkPolicy,
get_seed_reactions
);
}
gridfire::engine::DynamicEngine& PyNetworkPolicy::construct() {
PYBIND11_OVERRIDE_PURE(
gridfire::engine::DynamicEngine&,
gridfire::policy::NetworkPolicy,
construct
);
}
gridfire::policy::NetworkPolicyStatus PyNetworkPolicy::get_status() const {
PYBIND11_OVERRIDE_PURE(
gridfire::policy::NetworkPolicyStatus,
gridfire::policy::NetworkPolicy,
getStatus
);
}
const std::vector<std::unique_ptr<gridfire::engine::DynamicEngine>> &PyNetworkPolicy::get_engine_stack() const {
PYBIND11_OVERRIDE_PURE(
const std::vector<std::unique_ptr<gridfire::engine::DynamicEngine>> &,
gridfire::policy::NetworkPolicy,
get_engine_stack
);
}
std::vector<gridfire::engine::EngineTypes> PyNetworkPolicy::get_engine_types_stack() const {
PYBIND11_OVERRIDE_PURE(
std::vector<gridfire::engine::EngineTypes>,
gridfire::policy::NetworkPolicy,
get_engine_types_stack
);
}
const std::unique_ptr<gridfire::partition::PartitionFunction>& PyNetworkPolicy::get_partition_function() const {
PYBIND11_OVERRIDE_PURE(
const std::unique_ptr<gridfire::partition::PartitionFunction>&,
gridfire::policy::NetworkPolicy,
get_partition_function
);
}
const gridfire::reaction::ReactionSet &PyReactionChainPolicy::get_reactions() const {
PYBIND11_OVERRIDE_PURE(
const gridfire::reaction::ReactionSet &,
gridfire::policy::ReactionChainPolicy,
get_reactions
);
}
bool PyReactionChainPolicy::contains(const std::string &id) const {
PYBIND11_OVERRIDE_PURE(
bool,
gridfire::policy::ReactionChainPolicy,
contains,
id
);
}
bool PyReactionChainPolicy::contains(const gridfire::reaction::Reaction &reaction) const {
PYBIND11_OVERRIDE_PURE(
bool,
gridfire::policy::ReactionChainPolicy,
contains,
reaction
);
}
std::unique_ptr<gridfire::policy::ReactionChainPolicy> PyReactionChainPolicy::clone() const {
PYBIND11_OVERRIDE_PURE(
std::unique_ptr<gridfire::policy::ReactionChainPolicy>,
gridfire::policy::ReactionChainPolicy,
clone
);
}
std::string PyReactionChainPolicy::name() const {
PYBIND11_OVERRIDE_PURE(
std::string,
gridfire::policy::ReactionChainPolicy,
name
);
}
uint64_t PyReactionChainPolicy::hash(uint64_t seed) const {
PYBIND11_OVERRIDE_PURE(
uint64_t,
gridfire::policy::ReactionChainPolicy,
hash,
seed
);
}
bool PyReactionChainPolicy::operator==(const ReactionChainPolicy &other) const {
PYBIND11_OVERRIDE_PURE(
bool,
gridfire::policy::ReactionChainPolicy,
operator==,
other
);
}
bool PyReactionChainPolicy::operator!=(const ReactionChainPolicy &other) const {
PYBIND11_OVERRIDE_PURE(
bool,
gridfire::policy::ReactionChainPolicy,
operator!=,
other
);
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "gridfire/policy/policy.h"
class PyNetworkPolicy final : public gridfire::policy::NetworkPolicy {
public:
[[nodiscard]] std::string name() const override;
[[nodiscard]] const std::set<fourdst::atomic::Species>& get_seed_species() const override;
[[nodiscard]] const gridfire::reaction::ReactionSet& get_seed_reactions() const override;
[[nodiscard]] gridfire::engine::DynamicEngine& construct() override;
[[nodiscard]] gridfire::policy::NetworkPolicyStatus get_status() const override;
[[nodiscard]] const std::vector<std::unique_ptr<gridfire::engine::DynamicEngine>> &get_engine_stack() const override;
[[nodiscard]] std::vector<gridfire::engine::EngineTypes> get_engine_types_stack() const override;
[[nodiscard]] const std::unique_ptr<gridfire::partition::PartitionFunction>& get_partition_function() const override;
};
class PyReactionChainPolicy final : public gridfire::policy::ReactionChainPolicy {
public:
[[nodiscard]] const gridfire::reaction::ReactionSet & get_reactions() const override;
[[nodiscard]] bool contains(const std::string &id) const override;
[[nodiscard]] bool contains(const gridfire::reaction::Reaction &reaction) const override;
[[nodiscard]] std::unique_ptr<ReactionChainPolicy> clone() const override;
[[nodiscard]] std::string name() const override;
[[nodiscard]] uint64_t hash(uint64_t seed) const override;
[[nodiscard]] bool operator==(const ReactionChainPolicy &other) const override;
[[nodiscard]] bool operator!=(const ReactionChainPolicy &other) const override;
};

View File

@@ -1,12 +1,10 @@
#include <pybind11/pybind11.h>
#include <pybind11/functional.h> // needed for std::function
#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 <pybind11/numpy.h>
#include <pybind11/functional.h>
#include <functional>
#include <boost/numeric/ublas/vector.hpp>
#include "bindings.h"
#include "gridfire/solver/strategies/CVODE_solver_strategy.h"
@@ -37,7 +35,7 @@ void register_solver_bindings(const py::module &m) {
py_cvode_timestep_context.def_readonly("currentNonlinearIterations", &gridfire::solver::CVODESolverStrategy::TimestepContext::currentNonlinearIterations);
py_cvode_timestep_context.def_property_readonly(
"engine",
[](const gridfire::solver::CVODESolverStrategy::TimestepContext& self) -> const gridfire::DynamicEngine& {
[](const gridfire::solver::CVODESolverStrategy::TimestepContext& self) -> const gridfire::engine::DynamicEngine& {
return self.engine;
}
);
@@ -66,7 +64,7 @@ void register_solver_bindings(const py::module &m) {
auto py_cvode_solver_strategy = py::class_<gridfire::solver::CVODESolverStrategy, gridfire::solver::DynamicNetworkSolverStrategy>(m, "CVODESolverStrategy");
py_cvode_solver_strategy.def(
py::init<gridfire::DynamicEngine&>(),
py::init<gridfire::engine::DynamicEngine&>(),
py::arg("engine"),
"Initialize the CVODESolverStrategy object."
);
@@ -75,7 +73,7 @@ void register_solver_bindings(const py::module &m) {
"evaluate",
py::overload_cast<const gridfire::NetIn&, bool>(&gridfire::solver::CVODESolverStrategy::evaluate),
py::arg("netIn"),
py::arg("display_trigger"),
py::arg("display_trigger") = false,
"evaluate the dynamic engine using the dynamic engine class"
);
@@ -92,6 +90,32 @@ void register_solver_bindings(const py::module &m) {
"Enable logging to standard output."
);
py_cvode_solver_strategy.def(
"set_absTol",
&gridfire::solver::CVODESolverStrategy::set_absTol,
py::arg("absTol"),
"Set the absolute tolerance for the CVODE solver."
);
py_cvode_solver_strategy.def(
"set_relTol",
&gridfire::solver::CVODESolverStrategy::set_relTol,
py::arg("relTol"),
"Set the relative tolerance for the CVODE solver."
);
py_cvode_solver_strategy.def(
"get_absTol",
&gridfire::solver::CVODESolverStrategy::get_absTol,
"Get the absolute tolerance for the CVODE solver."
);
py_cvode_solver_strategy.def(
"get_relTol",
&gridfire::solver::CVODESolverStrategy::get_relTol,
"Get the relative tolerance for the CVODE solver."
);
py_cvode_solver_strategy.def(
"set_callback",
[](
@@ -103,7 +127,5 @@ void register_solver_bindings(const py::module &m) {
py::arg("cb"),
"Set a callback function which will run at the end of every successful timestep"
);
}

View File

@@ -8,7 +8,7 @@
#include <any>
class PyDynamicNetworkSolverStrategy final : public gridfire::solver::DynamicNetworkSolverStrategy {
explicit PyDynamicNetworkSolverStrategy(gridfire::DynamicEngine &engine) : gridfire::solver::DynamicNetworkSolverStrategy(engine) {}
explicit PyDynamicNetworkSolverStrategy(gridfire::engine::DynamicEngine &engine) : gridfire::solver::DynamicNetworkSolverStrategy(engine) {}
gridfire::NetOut evaluate(const gridfire::NetIn &netIn) override;
void set_callback(const std::any &callback) override;
[[nodiscard]] std::vector<std::tuple<std::string, std::string>> describe_callback_context() const override;

View File

@@ -7,7 +7,7 @@
namespace py = pybind11;
#include "gridfire/network.h"
#include "gridfire/types/types.h"
void register_type_bindings(const pybind11::module &m) {
py::class_<gridfire::NetIn>(m, "NetIn")