feat(network): added half lifes, spin flip parity, better reaction acritecture
This commit is contained in:
@@ -1,30 +1,99 @@
|
||||
#pragma once
|
||||
|
||||
#include "gridfire/network.h" // For NetIn, NetOut
|
||||
#include "../reaction/reaction.h"
|
||||
|
||||
#include "fourdst/composition/composition.h"
|
||||
#include "fourdst/config/config.h"
|
||||
#include "fourdst/logging/logging.h"
|
||||
#include "gridfire/reaction/reaction.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
/**
|
||||
* @file engine_abstract.h
|
||||
* @brief Abstract interfaces for reaction network engines in GridFire.
|
||||
*
|
||||
* This header defines the abstract base classes and concepts for implementing
|
||||
* reaction network solvers in the GridFire framework. It provides the contract
|
||||
* for calculating right-hand sides, energy generation, Jacobians, stoichiometry,
|
||||
* and other core operations required for time integration of nuclear reaction networks.
|
||||
*
|
||||
* @author
|
||||
* Emily M. Boudreaux
|
||||
*/
|
||||
|
||||
namespace gridfire {
|
||||
|
||||
/**
|
||||
* @brief Concept for types allowed in engine calculations.
|
||||
*
|
||||
* This concept restricts template parameters to either double or CppAD::AD<double>,
|
||||
* enabling both standard and automatic differentiation types.
|
||||
*/
|
||||
template<typename T>
|
||||
concept IsArithmeticOrAD = std::is_same_v<T, double> || std::is_same_v<T, CppAD::AD<double>>;
|
||||
|
||||
/**
|
||||
* @brief Structure holding derivatives and energy generation for a network step.
|
||||
*
|
||||
* @tparam T Numeric type (double or CppAD::AD<double>).
|
||||
*
|
||||
* This struct is used to return both the time derivatives of all species abundances
|
||||
* and the specific nuclear energy generation rate for a single network evaluation.
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* StepDerivatives<double> result = engine.calculateRHSAndEnergy(Y, T9, rho);
|
||||
* for (double dydt_i : result.dydt) {
|
||||
* // Use derivative
|
||||
* }
|
||||
* double energyRate = result.nuclearEnergyGenerationRate;
|
||||
* @endcode
|
||||
*/
|
||||
template <IsArithmeticOrAD T>
|
||||
struct StepDerivatives {
|
||||
std::vector<T> dydt; ///< Derivatives of abundances.
|
||||
T nuclearEnergyGenerationRate = T(0.0); ///< Specific energy generation rate.
|
||||
std::vector<T> dydt; ///< Derivatives of abundances (dY/dt for each species).
|
||||
T nuclearEnergyGenerationRate = T(0.0); ///< Specific energy generation rate (e.g., erg/g/s).
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for a reaction network engine.
|
||||
*
|
||||
* This class defines the minimal interface for a reaction network engine,
|
||||
* which is responsible for evaluating the right-hand side (dY/dt) and
|
||||
* energy generation for a given set of abundances, temperature, and density.
|
||||
*
|
||||
* Intended usage: Derive from this class to implement a concrete engine
|
||||
* for a specific network or integration method.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* class MyEngine : public gridfire::Engine {
|
||||
* // Implement required methods...
|
||||
* };
|
||||
* @endcode
|
||||
*/
|
||||
class Engine {
|
||||
public:
|
||||
/**
|
||||
* @brief Virtual destructor.
|
||||
*/
|
||||
virtual ~Engine() = default;
|
||||
|
||||
/**
|
||||
* @brief Get the list of species in the network.
|
||||
* @return Vector of Species objects representing all network species.
|
||||
*/
|
||||
virtual const std::vector<fourdst::atomic::Species>& getNetworkSpecies() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Calculate the right-hand side (dY/dt) and energy generation.
|
||||
*
|
||||
* @param Y Vector of current abundances for all species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return StepDerivatives<double> containing dY/dt and energy generation rate.
|
||||
*
|
||||
* This function must be implemented by derived classes to compute the
|
||||
* time derivatives of all species and the specific nuclear energy generation
|
||||
* rate for the current state.
|
||||
*/
|
||||
virtual StepDerivatives<double> calculateRHSAndEnergy(
|
||||
const std::vector<double>& Y,
|
||||
double T9,
|
||||
@@ -32,23 +101,85 @@ namespace gridfire {
|
||||
) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Abstract class for engines supporting Jacobian and stoichiometry operations.
|
||||
*
|
||||
* Extends Engine with additional methods for:
|
||||
* - Generating and accessing the Jacobian matrix (for implicit solvers).
|
||||
* - Generating and accessing the stoichiometry matrix.
|
||||
* - Calculating molar reaction flows for individual reactions.
|
||||
* - Accessing the set of logical reactions in the network.
|
||||
* - Computing timescales for each species.
|
||||
*
|
||||
* Intended usage: Derive from this class to implement engines that support
|
||||
* advanced solver features such as implicit integration, sensitivity analysis,
|
||||
* QSE (Quasi-Steady-State Equilibrium) handling, and more.
|
||||
*/
|
||||
class DynamicEngine : public Engine {
|
||||
public:
|
||||
/**
|
||||
* @brief Generate the Jacobian matrix for the current state.
|
||||
*
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
*
|
||||
* This method must compute and store the Jacobian matrix (∂(dY/dt)_i/∂Y_j)
|
||||
* for the current state. The matrix can then be accessed via getJacobianMatrixEntry().
|
||||
*/
|
||||
virtual void generateJacobianMatrix(
|
||||
const std::vector<double>& Y,
|
||||
double T9, double rho
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get an entry from the previously generated Jacobian matrix.
|
||||
*
|
||||
* @param i Row index (species index).
|
||||
* @param j Column index (species index).
|
||||
* @return Value of the Jacobian matrix at (i, j).
|
||||
*
|
||||
* The Jacobian must have been generated by generateJacobianMatrix() before calling this.
|
||||
*/
|
||||
virtual double getJacobianMatrixEntry(
|
||||
int i,
|
||||
int j
|
||||
) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Generate the stoichiometry matrix for the network.
|
||||
*
|
||||
* This method must compute and store the stoichiometry matrix,
|
||||
* which encodes the net change of each species in each reaction.
|
||||
*/
|
||||
virtual void generateStoichiometryMatrix() = 0;
|
||||
|
||||
/**
|
||||
* @brief Get an entry from the stoichiometry matrix.
|
||||
*
|
||||
* @param speciesIndex Index of the species.
|
||||
* @param reactionIndex Index of the reaction.
|
||||
* @return Stoichiometric coefficient for the species in the reaction.
|
||||
*
|
||||
* The stoichiometry matrix must have been generated by generateStoichiometryMatrix().
|
||||
*/
|
||||
virtual int getStoichiometryMatrixEntry(
|
||||
int speciesIndex,
|
||||
int reactionIndex
|
||||
) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Calculate the molar reaction flow for a given reaction.
|
||||
*
|
||||
* @param reaction The reaction for which to calculate the flow.
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Molar flow rate for the reaction (e.g., mol/g/s).
|
||||
*
|
||||
* This method computes the net rate at which the given reaction proceeds
|
||||
* under the current state.
|
||||
*/
|
||||
virtual double calculateMolarReactionFlow(
|
||||
const reaction::Reaction& reaction,
|
||||
const std::vector<double>& Y,
|
||||
@@ -56,7 +187,24 @@ namespace gridfire {
|
||||
double rho
|
||||
) const = 0;
|
||||
|
||||
virtual const reaction::REACLIBLogicalReactionSet& getNetworkReactions() const = 0;
|
||||
/**
|
||||
* @brief Get the set of logical reactions in the network.
|
||||
*
|
||||
* @return Reference to the LogicalReactionSet containing all reactions.
|
||||
*/
|
||||
virtual const reaction::LogicalReactionSet& getNetworkReactions() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Compute timescales for all species in the network.
|
||||
*
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Map from Species to their characteristic timescales (s).
|
||||
*
|
||||
* This method estimates the timescale for abundance change of each species,
|
||||
* which can be used for timestep control, diagnostics, and reaction network culling.
|
||||
*/
|
||||
virtual std::unordered_map<fourdst::atomic::Species, double> getSpeciesTimescales(
|
||||
const std::vector<double>& Y,
|
||||
double T9,
|
||||
|
||||
@@ -1,75 +1,316 @@
|
||||
#pragma once
|
||||
#include "gridfire/engine/engine_abstract.h"
|
||||
#include "gridfire/engine/engine_view_abstract.h"
|
||||
#include "gridfire/network.h"
|
||||
|
||||
#include "fourdst/composition/atomicSpecies.h"
|
||||
#include "fourdst/config/config.h"
|
||||
#include "fourdst/logging/logging.h"
|
||||
|
||||
#include "quill/Logger.h"
|
||||
|
||||
namespace gridfire {
|
||||
/**
|
||||
* @class AdaptiveEngineView
|
||||
* @brief An engine view that dynamically adapts the reaction network based on runtime conditions.
|
||||
*
|
||||
* This class implements an EngineView that dynamically culls species and reactions from the
|
||||
* full reaction network based on their reaction flow rates and connectivity. This allows for
|
||||
* efficient simulation of reaction networks by focusing computational effort on the most
|
||||
* important species and reactions.
|
||||
*
|
||||
* The AdaptiveEngineView maintains a subset of "active" species and reactions, and maps
|
||||
* between the full network indices and the active subset indices. This allows the base engine
|
||||
* to operate on the full network data, while the AdaptiveEngineView provides a reduced view
|
||||
* for external clients.
|
||||
*
|
||||
* The adaptation process is driven by the `update()` method, which performs the following steps:
|
||||
* 1. **Reaction Flow Calculation:** Calculates the molar reaction flow rate for each reaction
|
||||
* in the full network based on the current temperature, density, and composition.
|
||||
* 2. **Reaction Culling:** Culls reactions with flow rates below a threshold, determined by
|
||||
* a relative culling threshold multiplied by the maximum flow rate.
|
||||
* 3. **Connectivity Analysis:** Performs a connectivity analysis to identify species that are
|
||||
* reachable from the initial fuel species through the culled reaction network.
|
||||
* 4. **Species Culling:** Culls species that are not reachable from the initial fuel.
|
||||
* 5. **Index Map Construction:** Constructs index maps to map between the full network indices
|
||||
* and the active subset indices for species and reactions.
|
||||
*
|
||||
* @implements DynamicEngine
|
||||
* @implements EngineView<DynamicEngine>
|
||||
*
|
||||
* @see engine_abstract.h
|
||||
* @see engine_view_abstract.h
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
class AdaptiveEngineView final : public DynamicEngine, public EngineView<DynamicEngine> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an AdaptiveEngineView.
|
||||
*
|
||||
* @param baseEngine The underlying DynamicEngine to which this view delegates calculations.
|
||||
*
|
||||
* Initializes the active species and reactions to the full network, and constructs the
|
||||
* initial index maps.
|
||||
*/
|
||||
explicit AdaptiveEngineView(DynamicEngine& baseEngine);
|
||||
|
||||
/**
|
||||
* @brief Updates the active species and reactions based on the current conditions.
|
||||
*
|
||||
* @param netIn The current network input, containing temperature, density, and composition.
|
||||
*
|
||||
* This method performs the reaction flow calculation, reaction culling, connectivity analysis,
|
||||
* and index map construction steps described above.
|
||||
*
|
||||
* The culling thresholds are read from the configuration using the following keys:
|
||||
* - `gridfire:AdaptiveEngineView:RelativeCullingThreshold` (default: 1e-75)
|
||||
*
|
||||
* @throws std::runtime_error If there is a mismatch between the active reactions and the base engine.
|
||||
* @post The active species and reactions are updated, and the index maps are reconstructed.
|
||||
* @see AdaptiveEngineView
|
||||
* @see AdaptiveEngineView::constructSpeciesIndexMap()
|
||||
* @see AdaptiveEngineView::constructReactionIndexMap()
|
||||
*/
|
||||
void update(const NetIn& netIn);
|
||||
|
||||
/**
|
||||
* @brief Gets the list of active species in the network.
|
||||
* @return A const reference to the vector of active species.
|
||||
*/
|
||||
const std::vector<fourdst::atomic::Species>& getNetworkSpecies() const override;
|
||||
|
||||
/**
|
||||
* @brief Calculates the right-hand side (dY/dt) and energy generation for the active species.
|
||||
*
|
||||
* @param Y_culled A vector of abundances for the active species.
|
||||
* @param T9 The temperature in units of 10^9 K.
|
||||
* @param rho The density in g/cm^3.
|
||||
* @return A StepDerivatives struct containing the derivatives of the active species and the
|
||||
* nuclear energy generation rate.
|
||||
*
|
||||
* This method maps the culled abundances to the full network abundances, calls the base engine
|
||||
* to calculate the RHS and energy generation, and then maps the full network derivatives back
|
||||
* to the culled derivatives.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
StepDerivatives<double> calculateRHSAndEnergy(
|
||||
const std::vector<double> &Y,
|
||||
const std::vector<double> &Y_culled,
|
||||
const double T9,
|
||||
const double rho
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Generates the Jacobian matrix for the active species.
|
||||
*
|
||||
* @param Y_culled A vector of abundances for the active species.
|
||||
* @param T9 The temperature in units of 10^9 K.
|
||||
* @param rho The density in g/cm^3.
|
||||
*
|
||||
* This method maps the culled abundances to the full network abundances and calls the base engine
|
||||
* to generate the Jacobian matrix.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
void generateJacobianMatrix(
|
||||
const std::vector<double> &Y,
|
||||
const std::vector<double> &Y_culled,
|
||||
const double T9,
|
||||
const double rho
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Gets an entry from the Jacobian matrix for the active species.
|
||||
*
|
||||
* @param i_culled The row index (species index) in the culled matrix.
|
||||
* @param j_culled The column index (species index) in the culled matrix.
|
||||
* @return The value of the Jacobian matrix at (i_culled, j_culled).
|
||||
*
|
||||
* This method maps the culled indices to the full network indices and calls the base engine
|
||||
* to get the Jacobian matrix entry.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
* @throws std::out_of_range If the culled index is out of bounds for the species index map.
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
double getJacobianMatrixEntry(
|
||||
const int i,
|
||||
const int j
|
||||
const int i_culled,
|
||||
const int j_culled
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Generates the stoichiometry matrix for the active reactions and species.
|
||||
*
|
||||
* This method calls the base engine to generate the stoichiometry matrix.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
* @note The stoichiometry matrix generated by the base engine is assumed to be consistent with
|
||||
* the active species and reactions in this view.
|
||||
*/
|
||||
void generateStoichiometryMatrix() override;
|
||||
|
||||
/**
|
||||
* @brief Gets an entry from the stoichiometry matrix for the active species and reactions.
|
||||
*
|
||||
* @param speciesIndex_culled The index of the species in the culled species list.
|
||||
* @param reactionIndex_culled The index of the reaction in the culled reaction list.
|
||||
* @return The stoichiometric coefficient for the given species and reaction.
|
||||
*
|
||||
* This method maps the culled indices to the full network indices and calls the base engine
|
||||
* to get the stoichiometry matrix entry.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
* @throws std::out_of_range If the culled index is out of bounds for the species or reaction index map.
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
int getStoichiometryMatrixEntry(
|
||||
const int speciesIndex,
|
||||
const int reactionIndex
|
||||
const int speciesIndex_culled,
|
||||
const int reactionIndex_culled
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Calculates the molar reaction flow for a given reaction in the active network.
|
||||
*
|
||||
* @param reaction The reaction for which to calculate the flow.
|
||||
* @param Y_culled Vector of current abundances for the active species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Molar flow rate for the reaction (e.g., mol/g/s).
|
||||
*
|
||||
* This method maps the culled abundances to the full network abundances and calls the base engine
|
||||
* to calculate the molar reaction flow.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
* @throws std::runtime_error If the reaction is not part of the active reactions in the adaptive engine view.
|
||||
*/
|
||||
double calculateMolarReactionFlow(
|
||||
const reaction::Reaction &reaction,
|
||||
const std::vector<double> &Y,
|
||||
const std::vector<double> &Y_culled,
|
||||
double T9,
|
||||
double rho
|
||||
) const override;
|
||||
|
||||
const reaction::REACLIBLogicalReactionSet& getNetworkReactions() const override;
|
||||
/**
|
||||
* @brief Gets the set of active logical reactions in the network.
|
||||
*
|
||||
* @return Reference to the LogicalReactionSet containing all active reactions.
|
||||
*/
|
||||
const reaction::LogicalReactionSet& getNetworkReactions() const override;
|
||||
|
||||
/**
|
||||
* @brief Computes timescales for all active species in the network.
|
||||
*
|
||||
* @param Y_culled Vector of current abundances for the active species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Map from Species to their characteristic timescales (s).
|
||||
*
|
||||
* This method maps the culled abundances to the full network abundances and calls the base engine
|
||||
* to compute the species timescales.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
*/
|
||||
std::unordered_map<fourdst::atomic::Species, double> getSpeciesTimescales(
|
||||
const std::vector<double> &Y,
|
||||
const std::vector<double> &Y_culled,
|
||||
double T9,
|
||||
double rho
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Gets the base engine.
|
||||
* @return A const reference to the base engine.
|
||||
*/
|
||||
const DynamicEngine& getBaseEngine() const override { return m_baseEngine; }
|
||||
private:
|
||||
using Config = fourdst::config::Config;
|
||||
using LogManager = fourdst::logging::LogManager;
|
||||
Config& m_config = Config::getInstance();
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
|
||||
DynamicEngine& m_baseEngine;
|
||||
|
||||
std::vector<fourdst::atomic::Species> m_activeSpecies;
|
||||
reaction::REACLIBLogicalReactionSet m_activeReactions;
|
||||
reaction::LogicalReactionSet m_activeReactions;
|
||||
|
||||
std::vector<size_t> m_speciesIndexMap;
|
||||
std::vector<size_t> m_reactionIndexMap;
|
||||
|
||||
bool m_isStale = true;
|
||||
|
||||
Config& m_config = Config::getInstance();
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
private:
|
||||
/**
|
||||
* @brief Constructs the species index map.
|
||||
*
|
||||
* @return A vector mapping culled species indices to full species indices.
|
||||
*
|
||||
* This method creates a map from the indices of the active species to the indices of the
|
||||
* corresponding species in the full network.
|
||||
*
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
std::vector<size_t> constructSpeciesIndexMap() const;
|
||||
|
||||
/**
|
||||
* @brief Constructs the reaction index map.
|
||||
*
|
||||
* @return A vector mapping culled reaction indices to full reaction indices.
|
||||
*
|
||||
* This method creates a map from the indices of the active reactions to the indices of the
|
||||
* corresponding reactions in the full network.
|
||||
*
|
||||
* @see AdaptiveEngineView::update()
|
||||
*/
|
||||
std::vector<size_t> constructReactionIndexMap() const;
|
||||
|
||||
/**
|
||||
* @brief Maps a vector of culled abundances to a vector of full abundances.
|
||||
*
|
||||
* @param culled A vector of abundances for the active species.
|
||||
* @return A vector of abundances for the full network, with the abundances of the active
|
||||
* species copied from the culled vector.
|
||||
*/
|
||||
std::vector<double> mapCulledToFull(const std::vector<double>& culled) const;
|
||||
|
||||
/**
|
||||
* @brief Maps a vector of full abundances to a vector of culled abundances.
|
||||
*
|
||||
* @param full A vector of abundances for the full network.
|
||||
* @return A vector of abundances for the active species, with the abundances of the active
|
||||
* species copied from the full vector.
|
||||
*/
|
||||
std::vector<double> mapFullToCulled(const std::vector<double>& full) const;
|
||||
|
||||
/**
|
||||
* @brief Maps a culled species index to a full species index.
|
||||
*
|
||||
* @param culledSpeciesIndex The index of the species in the culled species list.
|
||||
* @return The index of the corresponding species in the full network.
|
||||
*
|
||||
* @throws std::out_of_range If the culled index is out of bounds for the species index map.
|
||||
*/
|
||||
size_t mapCulledToFullSpeciesIndex(size_t culledSpeciesIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Maps a culled reaction index to a full reaction index.
|
||||
*
|
||||
* @param culledReactionIndex The index of the reaction in the culled reaction list.
|
||||
* @return The index of the corresponding reaction in the full network.
|
||||
*
|
||||
* @throws std::out_of_range If the culled index is out of bounds for the reaction index map.
|
||||
*/
|
||||
size_t mapCulledToFullReactionIndex(size_t culledReactionIndex) const;
|
||||
|
||||
/**
|
||||
* @brief Validates that the AdaptiveEngineView is not stale.
|
||||
*
|
||||
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
|
||||
*/
|
||||
void validateState() const;
|
||||
private:
|
||||
/**
|
||||
* @brief A struct to hold a reaction and its flow rate.
|
||||
*/
|
||||
struct ReactionFlow {
|
||||
const reaction::Reaction* reactionPtr;
|
||||
double flowRate;
|
||||
|
||||
@@ -23,35 +23,148 @@
|
||||
// REACLIBReactions are quite large data structures, so this could be a performance bottleneck.
|
||||
|
||||
namespace gridfire {
|
||||
typedef CppAD::AD<double> ADDouble; ///< Alias for CppAD AD type for double precision.
|
||||
/**
|
||||
* @brief Alias for CppAD AD type for double precision.
|
||||
*
|
||||
* This alias simplifies the use of the CppAD automatic differentiation type.
|
||||
*/
|
||||
typedef CppAD::AD<double> ADDouble;
|
||||
|
||||
using fourdst::config::Config;
|
||||
using fourdst::logging::LogManager;
|
||||
using fourdst::constant::Constants;
|
||||
|
||||
/**
|
||||
* @brief Minimum density threshold below which reactions are ignored.
|
||||
*
|
||||
* Reactions are not calculated if the density falls below this threshold.
|
||||
* This helps to improve performance by avoiding unnecessary calculations
|
||||
* in very low-density regimes.
|
||||
*/
|
||||
static constexpr double MIN_DENSITY_THRESHOLD = 1e-18;
|
||||
|
||||
/**
|
||||
* @brief Minimum abundance threshold below which species are ignored.
|
||||
*
|
||||
* Species with abundances below this threshold are treated as zero in
|
||||
* reaction rate calculations. This helps to improve performance by
|
||||
* avoiding unnecessary calculations for trace species.
|
||||
*/
|
||||
static constexpr double MIN_ABUNDANCE_THRESHOLD = 1e-18;
|
||||
|
||||
/**
|
||||
* @brief Minimum value for Jacobian matrix entries.
|
||||
*
|
||||
* Jacobian matrix entries with absolute values below this threshold are
|
||||
* treated as zero to maintain sparsity and improve performance.
|
||||
*/
|
||||
static constexpr double MIN_JACOBIAN_THRESHOLD = 1e-24;
|
||||
|
||||
/**
|
||||
* @class GraphEngine
|
||||
* @brief A reaction network engine that uses a graph-based representation.
|
||||
*
|
||||
* The GraphEngine class implements the DynamicEngine interface using a
|
||||
* graph-based representation of the reaction network. It uses sparse
|
||||
* matrices for efficient storage and computation of the stoichiometry
|
||||
* and Jacobian matrices. Automatic differentiation (AD) is used to
|
||||
* calculate the Jacobian matrix.
|
||||
*
|
||||
* The engine supports:
|
||||
* - Calculation of the right-hand side (dY/dt) and energy generation rate.
|
||||
* - Generation and access to the Jacobian matrix.
|
||||
* - Generation and access to the stoichiometry matrix.
|
||||
* - Calculation of molar reaction flows.
|
||||
* - Access to the set of logical reactions in the network.
|
||||
* - Computation of timescales for each species.
|
||||
* - Exporting the network to DOT and CSV formats for visualization and analysis.
|
||||
*
|
||||
* @implements DynamicEngine
|
||||
*
|
||||
* @see engine_abstract.h
|
||||
*/
|
||||
class GraphEngine final : public DynamicEngine{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a GraphEngine from a composition.
|
||||
*
|
||||
* @param composition The composition of the material.
|
||||
*
|
||||
* This constructor builds the reaction network from the given composition
|
||||
* using the `build_reaclib_nuclear_network` function.
|
||||
*
|
||||
* @see build_reaclib_nuclear_network
|
||||
*/
|
||||
explicit GraphEngine(const fourdst::composition::Composition &composition);
|
||||
explicit GraphEngine(reaction::REACLIBLogicalReactionSet reactions);
|
||||
|
||||
/**
|
||||
* @brief Constructs a GraphEngine from a set of reactions.
|
||||
*
|
||||
* @param reactions The set of reactions to use in the network.
|
||||
*
|
||||
* This constructor uses the given set of reactions to construct the
|
||||
* reaction network.
|
||||
*/
|
||||
explicit GraphEngine(reaction::LogicalReactionSet reactions);
|
||||
|
||||
/**
|
||||
* @brief Calculates the right-hand side (dY/dt) and energy generation rate.
|
||||
*
|
||||
* @param Y Vector of current abundances for all species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return StepDerivatives<double> containing dY/dt and energy generation rate.
|
||||
*
|
||||
* This method calculates the time derivatives of all species and the
|
||||
* specific nuclear energy generation rate for the current state.
|
||||
*
|
||||
* @see StepDerivatives
|
||||
*/
|
||||
StepDerivatives<double> calculateRHSAndEnergy(
|
||||
const std::vector<double>& Y,
|
||||
const double T9,
|
||||
const double rho
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Generates the Jacobian matrix for the current state.
|
||||
*
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
*
|
||||
* This method computes and stores the Jacobian matrix (∂(dY/dt)_i/∂Y_j)
|
||||
* for the current state using automatic differentiation. The matrix can
|
||||
* then be accessed via `getJacobianMatrixEntry()`.
|
||||
*
|
||||
* @see getJacobianMatrixEntry()
|
||||
*/
|
||||
void generateJacobianMatrix(
|
||||
const std::vector<double>& Y,
|
||||
const double T9,
|
||||
const double rho
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Generates the stoichiometry matrix for the network.
|
||||
*
|
||||
* This method computes and stores the stoichiometry matrix,
|
||||
* which encodes the net change of each species in each reaction.
|
||||
*/
|
||||
void generateStoichiometryMatrix() override;
|
||||
|
||||
/**
|
||||
* @brief Calculates the molar reaction flow for a given reaction.
|
||||
*
|
||||
* @param reaction The reaction for which to calculate the flow.
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Molar flow rate for the reaction (e.g., mol/g/s).
|
||||
*
|
||||
* This method computes the net rate at which the given reaction proceeds
|
||||
* under the current state.
|
||||
*/
|
||||
double calculateMolarReactionFlow(
|
||||
const reaction::Reaction& reaction,
|
||||
const std::vector<double>&Y,
|
||||
@@ -59,39 +172,130 @@ namespace gridfire {
|
||||
const double rho
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Gets the list of species in the network.
|
||||
* @return Vector of Species objects representing all network species.
|
||||
*/
|
||||
[[nodiscard]] const std::vector<fourdst::atomic::Species>& getNetworkSpecies() const override;
|
||||
[[nodiscard]] const reaction::REACLIBLogicalReactionSet& getNetworkReactions() const override;
|
||||
|
||||
/**
|
||||
* @brief Gets the set of logical reactions in the network.
|
||||
* @return Reference to the LogicalReactionSet containing all reactions.
|
||||
*/
|
||||
[[nodiscard]] const reaction::LogicalReactionSet& getNetworkReactions() const override;
|
||||
|
||||
/**
|
||||
* @brief Gets an entry from the previously generated Jacobian matrix.
|
||||
*
|
||||
* @param i Row index (species index).
|
||||
* @param j Column index (species index).
|
||||
* @return Value of the Jacobian matrix at (i, j).
|
||||
*
|
||||
* The Jacobian must have been generated by `generateJacobianMatrix()` before calling this.
|
||||
*
|
||||
* @see generateJacobianMatrix()
|
||||
*/
|
||||
[[nodiscard]] double getJacobianMatrixEntry(
|
||||
const int i,
|
||||
const int j
|
||||
) const override;
|
||||
[[nodiscard]] std::unordered_map<fourdst::atomic::Species, int> getNetReactionStoichiometry(
|
||||
|
||||
/**
|
||||
* @brief Gets the net stoichiometry for a given reaction.
|
||||
*
|
||||
* @param reaction The reaction for which to get the stoichiometry.
|
||||
* @return Map of species to their stoichiometric coefficients.
|
||||
*/
|
||||
[[nodiscard]] static std::unordered_map<fourdst::atomic::Species, int> getNetReactionStoichiometry(
|
||||
const reaction::Reaction& reaction
|
||||
) const;
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Gets an entry from the stoichiometry matrix.
|
||||
*
|
||||
* @param speciesIndex Index of the species.
|
||||
* @param reactionIndex Index of the reaction.
|
||||
* @return Stoichiometric coefficient for the species in the reaction.
|
||||
*
|
||||
* The stoichiometry matrix must have been generated by `generateStoichiometryMatrix()`.
|
||||
*
|
||||
* @see generateStoichiometryMatrix()
|
||||
*/
|
||||
[[nodiscard]] int getStoichiometryMatrixEntry(
|
||||
const int speciesIndex,
|
||||
const int reactionIndex
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Computes timescales for all species in the network.
|
||||
*
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Map from Species to their characteristic timescales (s).
|
||||
*
|
||||
* This method estimates the timescale for abundance change of each species,
|
||||
* which can be used for timestep control or diagnostics.
|
||||
*/
|
||||
[[nodiscard]] std::unordered_map<fourdst::atomic::Species, double> getSpeciesTimescales(
|
||||
const std::vector<double>& Y,
|
||||
double T9,
|
||||
double rho
|
||||
) const override;
|
||||
|
||||
/**
|
||||
* @brief Checks if a given species is involved in the network.
|
||||
*
|
||||
* @param species The species to check.
|
||||
* @return True if the species is involved in the network, false otherwise.
|
||||
*/
|
||||
[[nodiscard]] bool involvesSpecies(
|
||||
const fourdst::atomic::Species& species
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Exports the network to a DOT file for visualization.
|
||||
*
|
||||
* @param filename The name of the DOT file to create.
|
||||
*
|
||||
* This method generates a DOT file that can be used to visualize the
|
||||
* reaction network as a graph. The DOT file can be converted to a
|
||||
* graphical image using Graphviz.
|
||||
*
|
||||
* @throws std::runtime_error If the file cannot be opened for writing.
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* engine.exportToDot("network.dot");
|
||||
* @endcode
|
||||
*/
|
||||
void exportToDot(
|
||||
const std::string& filename
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Exports the network to a CSV file for analysis.
|
||||
*
|
||||
* @param filename The name of the CSV file to create.
|
||||
*
|
||||
* This method generates a CSV file containing information about the
|
||||
* reactions in the network, including the reactants, products, Q-value,
|
||||
* and reaction rate coefficients.
|
||||
*
|
||||
* @throws std::runtime_error If the file cannot be opened for writing.
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* engine.exportToCSV("network.csv");
|
||||
* @endcode
|
||||
*/
|
||||
void exportToCSV(
|
||||
const std::string& filename
|
||||
) const;
|
||||
|
||||
|
||||
private:
|
||||
reaction::REACLIBLogicalReactionSet m_reactions; ///< Set of REACLIB reactions in the network.
|
||||
reaction::LogicalReactionSet m_reactions; ///< Set of REACLIB reactions in the network.
|
||||
std::unordered_map<std::string_view, reaction::Reaction*> m_reactionIDMap; ///< Map from reaction ID to REACLIBReaction. //PERF: This makes copies of REACLIBReaction and could be a performance bottleneck.
|
||||
|
||||
std::vector<fourdst::atomic::Species> m_networkSpecies; ///< Vector of unique species in the network.
|
||||
@@ -108,20 +312,100 @@ namespace gridfire {
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Synchronizes the internal maps.
|
||||
*
|
||||
* This method synchronizes the internal maps used by the engine,
|
||||
* including the species map, reaction ID map, and species-to-index map.
|
||||
* It also generates the stoichiometry matrix and records the AD tape.
|
||||
*/
|
||||
void syncInternalMaps();
|
||||
|
||||
/**
|
||||
* @brief Collects the unique species in the network.
|
||||
*
|
||||
* This method collects the unique species in the network from the
|
||||
* reactants and products of all reactions.
|
||||
*/
|
||||
void collectNetworkSpecies();
|
||||
|
||||
/**
|
||||
* @brief Populates the reaction ID map.
|
||||
*
|
||||
* This method populates the reaction ID map, which maps reaction IDs
|
||||
* to REACLIBReaction objects.
|
||||
*/
|
||||
void populateReactionIDMap();
|
||||
|
||||
/**
|
||||
* @brief Populates the species-to-index map.
|
||||
*
|
||||
* This method populates the species-to-index map, which maps species
|
||||
* to their index in the stoichiometry matrix.
|
||||
*/
|
||||
void populateSpeciesToIndexMap();
|
||||
|
||||
/**
|
||||
* @brief Reserves space for the Jacobian matrix.
|
||||
*
|
||||
* This method reserves space for the Jacobian matrix, which is used
|
||||
* to store the partial derivatives of the right-hand side of the ODE
|
||||
* with respect to the species abundances.
|
||||
*/
|
||||
void reserveJacobianMatrix();
|
||||
|
||||
/**
|
||||
* @brief Records the AD tape for the right-hand side of the ODE.
|
||||
*
|
||||
* This method records the AD tape for the right-hand side of the ODE,
|
||||
* which is used to calculate the Jacobian matrix using automatic
|
||||
* differentiation.
|
||||
*
|
||||
* @throws std::runtime_error If there are no species in the network.
|
||||
*/
|
||||
void recordADTape();
|
||||
|
||||
/**
|
||||
* @brief Validates mass and charge conservation across all reactions.
|
||||
*
|
||||
* @return True if all reactions conserve mass and charge, false otherwise.
|
||||
*
|
||||
* This method checks that all reactions in the network conserve mass
|
||||
* and charge. If any reaction does not conserve mass or charge, an
|
||||
* error message is logged and false is returned.
|
||||
*/
|
||||
[[nodiscard]] bool validateConservation() const;
|
||||
|
||||
/**
|
||||
* @brief Validates the composition against the current reaction set.
|
||||
*
|
||||
* @param composition The composition to validate.
|
||||
* @param culling The culling threshold to use.
|
||||
* @param T9 The temperature to use.
|
||||
*
|
||||
* This method validates the composition against the current reaction set.
|
||||
* If the composition is not compatible with the reaction set, the
|
||||
* reaction set is rebuilt from the composition.
|
||||
*/
|
||||
void validateComposition(
|
||||
const fourdst::composition::Composition &composition,
|
||||
double culling,
|
||||
double T9
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Calculates the molar reaction flow for a given reaction.
|
||||
*
|
||||
* @tparam T The numeric type to use for the calculation.
|
||||
* @param reaction The reaction for which to calculate the flow.
|
||||
* @param Y Vector of current abundances.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return Molar flow rate for the reaction (e.g., mol/g/s).
|
||||
*
|
||||
* This method computes the net rate at which the given reaction proceeds
|
||||
* under the current state.
|
||||
*/
|
||||
template <IsArithmeticOrAD T>
|
||||
T calculateMolarReactionFlow(
|
||||
const reaction::Reaction &reaction,
|
||||
@@ -130,6 +414,18 @@ namespace gridfire {
|
||||
const T rho
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Calculates all derivatives (dY/dt) and the energy generation rate.
|
||||
*
|
||||
* @tparam T The numeric type to use for the calculation.
|
||||
* @param Y_in Vector of current abundances for all species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return StepDerivatives<T> containing dY/dt and energy generation rate.
|
||||
*
|
||||
* This method calculates the time derivatives of all species and the
|
||||
* specific nuclear energy generation rate for the current state.
|
||||
*/
|
||||
template<IsArithmeticOrAD T>
|
||||
StepDerivatives<T> calculateAllDerivatives(
|
||||
const std::vector<T> &Y_in,
|
||||
@@ -137,16 +433,40 @@ namespace gridfire {
|
||||
T rho
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Calculates all derivatives (dY/dt) and the energy generation rate (double precision).
|
||||
*
|
||||
* @param Y_in Vector of current abundances for all species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return StepDerivatives<double> containing dY/dt and energy generation rate.
|
||||
*
|
||||
* This method calculates the time derivatives of all species and the
|
||||
* specific nuclear energy generation rate for the current state using
|
||||
* double precision arithmetic.
|
||||
*/
|
||||
StepDerivatives<double> calculateAllDerivatives(
|
||||
const std::vector<double>& Y_in,
|
||||
const double T9,
|
||||
const double rho
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @brief Calculates all derivatives (dY/dt) and the energy generation rate (automatic differentiation).
|
||||
*
|
||||
* @param Y_in Vector of current abundances for all species.
|
||||
* @param T9 Temperature in units of 10^9 K.
|
||||
* @param rho Density in g/cm^3.
|
||||
* @return StepDerivatives<ADDouble> containing dY/dt and energy generation rate.
|
||||
*
|
||||
* This method calculates the time derivatives of all species and the
|
||||
* specific nuclear energy generation rate for the current state using
|
||||
* automatic differentiation.
|
||||
*/
|
||||
StepDerivatives<ADDouble> calculateAllDerivatives(
|
||||
const std::vector<ADDouble>& Y_in,
|
||||
const ADDouble T9,
|
||||
const ADDouble rho
|
||||
const ADDouble &T9,
|
||||
const ADDouble &rho
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,98 @@
|
||||
//
|
||||
// Created by Emily Boudreaux on 6/27/25.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef ENGINE_VIEW_ABSTRACT_H
|
||||
#define ENGINE_VIEW_ABSTRACT_H
|
||||
#include "gridfire/engine/engine_abstract.h"
|
||||
|
||||
#endif //ENGINE_VIEW_ABSTRACT_H
|
||||
/**
|
||||
* @file engine_view_abstract.h
|
||||
* @brief Abstract interfaces for engine "views" in GridFire.
|
||||
*
|
||||
* This header defines the abstract base classes and concepts for "views" of reaction network engines.
|
||||
* The primary purpose of an EngineView is to enable dynamic or adaptive network topologies
|
||||
* (such as species/reaction culling, masking, or remapping) without modifying the underlying
|
||||
* physics engine or its implementation. Engine views act as a flexible interface layer,
|
||||
* allowing the network structure to be changed at runtime while preserving the core
|
||||
* physics and solver logic in the base engine.
|
||||
*
|
||||
* Typical use cases include:
|
||||
* - Adaptive or reduced networks for computational efficiency.
|
||||
* - Dynamic masking or culling of species/reactions based on runtime criteria.
|
||||
* - Providing a filtered or remapped view of the network for integration or analysis.
|
||||
* - Supporting dynamic network reconfiguration in multi-zone or multi-physics contexts.
|
||||
*
|
||||
* The base engine types referenced here are defined in @ref engine_abstract.h.
|
||||
*
|
||||
* @author
|
||||
* Emily M. Boudreaux
|
||||
*/
|
||||
|
||||
namespace gridfire {
|
||||
|
||||
/**
|
||||
* @brief Concept for types allowed as engine bases in EngineView.
|
||||
*
|
||||
* This concept restricts template parameters to types derived from either
|
||||
* gridfire::Engine or gridfire::DynamicEngine, as defined in engine_abstract.h.
|
||||
*
|
||||
* Example usage:
|
||||
* @code
|
||||
* static_assert(EngineType<MyEngine>);
|
||||
* @endcode
|
||||
*/
|
||||
template<typename EngineT>
|
||||
concept EngineType = std::is_base_of_v<Engine, EngineT> || std::is_base_of_v<DynamicEngine, EngineT>;
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for a "view" of a reaction network engine.
|
||||
*
|
||||
* @tparam EngineT The engine type being viewed (must satisfy EngineType).
|
||||
*
|
||||
* EngineView provides an interface for accessing an underlying engine instance,
|
||||
* while presenting a potentially modified or reduced network structure to the user.
|
||||
* This enables dynamic or adaptive network topologies (e.g., culling, masking, or
|
||||
* remapping of species and reactions) without altering the core physics engine.
|
||||
*
|
||||
* Intended usage: Derive from this class to implement a custom view or wrapper
|
||||
* that manages a dynamic or adaptive network structure, delegating core calculations
|
||||
* to the base engine. The contract is that getBaseEngine() must return a reference
|
||||
* to the underlying engine instance, which remains responsible for the full physics.
|
||||
*
|
||||
* Example (see also AdaptiveEngineView):
|
||||
* @code
|
||||
* class MyAdaptiveView : public gridfire::EngineView<DynamicEngine> {
|
||||
* public:
|
||||
* MyAdaptiveView(DynamicEngine& engine) : engine_(engine) {}
|
||||
* const DynamicEngine& getBaseEngine() const override { return engine_; }
|
||||
* // Implement dynamic masking/culling logic...
|
||||
* private:
|
||||
* DynamicEngine& engine_;
|
||||
* };
|
||||
* @endcode
|
||||
*
|
||||
* @see gridfire::AdaptiveEngineView for a concrete example of dynamic culling.
|
||||
*/
|
||||
template<EngineType EngineT>
|
||||
class EngineView {
|
||||
public:
|
||||
/**
|
||||
* @brief Virtual destructor.
|
||||
*/
|
||||
virtual ~EngineView() = default;
|
||||
|
||||
/**
|
||||
* @brief Access the underlying engine instance.
|
||||
*
|
||||
* @return Const reference to the underlying engine.
|
||||
*
|
||||
* This method must be implemented by derived classes to provide access
|
||||
* to the base engine. The returned reference should remain valid for the
|
||||
* lifetime of the EngineView.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* const DynamicEngine& engine = myView.getBaseEngine();
|
||||
* @endcode
|
||||
*/
|
||||
virtual const EngineT& getBaseEngine() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user