feat(GridFire): Much more robust starting network
GraphEngine now can initialize with a much more robust set of reactions (including the entire reaction set). The jacobian can still be efficiently evaluated using CppAD's sparse jacobian feature. Further, the primeing network has been signifiganty enhanced to handle much hotter termperatures
This commit is contained in:
@@ -5,8 +5,12 @@
|
||||
#include "gridfire/screening/screening_abstract.h"
|
||||
#include "gridfire/screening/screening_types.h"
|
||||
|
||||
#include "gridfire/engine/types/reporting.h"
|
||||
#include "gridfire/engine/types/building.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @file engine_abstract.h
|
||||
@@ -55,6 +59,8 @@ namespace gridfire {
|
||||
T nuclearEnergyGenerationRate = T(0.0); ///< Specific energy generation rate (e.g., erg/g/s).
|
||||
};
|
||||
|
||||
using SparsityPattern = std::vector<std::pair<size_t, size_t>>;
|
||||
|
||||
/**
|
||||
* @brief Abstract base class for a reaction network engine.
|
||||
*
|
||||
@@ -132,9 +138,19 @@ namespace gridfire {
|
||||
*/
|
||||
virtual void generateJacobianMatrix(
|
||||
const std::vector<double>& Y_dynamic,
|
||||
double T9, double rho
|
||||
double T9,
|
||||
double rho
|
||||
) = 0;
|
||||
|
||||
virtual void generateJacobianMatrix(
|
||||
const std::vector<double>& Y_dynamic,
|
||||
double T9,
|
||||
double rho,
|
||||
const SparsityPattern& sparsityPattern
|
||||
) {
|
||||
throw std::logic_error("Sparsity pattern not supported by this engine.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an entry from the previously generated Jacobian matrix.
|
||||
*
|
||||
@@ -149,6 +165,7 @@ namespace gridfire {
|
||||
int j
|
||||
) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate the stoichiometry matrix for the network.
|
||||
*
|
||||
@@ -269,5 +286,15 @@ namespace gridfire {
|
||||
[[nodiscard]] virtual int getSpeciesIndex(const fourdst::atomic::Species &species) const = 0;
|
||||
|
||||
[[nodiscard]] virtual std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const = 0;
|
||||
|
||||
[[nodiscard]] virtual PrimingReport primeEngine(const NetIn &netIn) = 0;
|
||||
|
||||
[[nodiscard]] virtual BuildDepthType getDepth() const {
|
||||
throw std::logic_error("Network depth not supported by this engine.");
|
||||
}
|
||||
|
||||
virtual void rebuild(const fourdst::composition::Composition& comp, BuildDepthType depth) {
|
||||
throw std::logic_error("Setting network depth not supported by this engine.");
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "gridfire/screening/screening_abstract.h"
|
||||
#include "gridfire/screening/screening_types.h"
|
||||
#include "gridfire/partition/partition_abstract.h"
|
||||
#include "gridfire/partition/partition_ground.h"
|
||||
#include "gridfire/engine/procedures/construction.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -22,6 +22,12 @@
|
||||
#include <boost/numeric/ublas/matrix_sparse.hpp>
|
||||
|
||||
#include "cppad/cppad.hpp"
|
||||
#include "cppad/utility/sparse_rc.hpp"
|
||||
#include "cppad/speed/sparse_jac_fun.hpp"
|
||||
|
||||
#include "procedures/priming.h"
|
||||
|
||||
|
||||
#include "quill/LogMacros.h"
|
||||
|
||||
// PERF: The function getNetReactionStoichiometry returns a map of species to their stoichiometric coefficients for a given reaction.
|
||||
@@ -30,6 +36,7 @@
|
||||
// REACLIBReactions are quite large data structures, so this could be a performance bottleneck.
|
||||
|
||||
namespace gridfire {
|
||||
static bool s_debug = false; // Global debug flag for the GraphEngine
|
||||
/**
|
||||
* @brief Alias for CppAD AD type for double precision.
|
||||
*
|
||||
@@ -103,11 +110,16 @@ namespace gridfire {
|
||||
*
|
||||
* @see build_reaclib_nuclear_network
|
||||
*/
|
||||
explicit GraphEngine(const fourdst::composition::Composition &composition);
|
||||
explicit GraphEngine(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const BuildDepthType = NetworkBuildDepth::Full
|
||||
);
|
||||
|
||||
explicit GraphEngine(const fourdst::composition::Composition &composition,
|
||||
const partition::PartitionFunction& partitionFunction
|
||||
);
|
||||
explicit GraphEngine(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const partition::PartitionFunction& partitionFunction,
|
||||
const BuildDepthType buildDepth = NetworkBuildDepth::Full
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Constructs a GraphEngine from a set of reactions.
|
||||
@@ -157,6 +169,13 @@ namespace gridfire {
|
||||
const double rho
|
||||
) override;
|
||||
|
||||
void generateJacobianMatrix(
|
||||
const std::vector<double> &Y_dynamic,
|
||||
double T9,
|
||||
double rho,
|
||||
const SparsityPattern &sparsityPattern
|
||||
) override;
|
||||
|
||||
/**
|
||||
* @brief Generates the stoichiometry matrix for the network.
|
||||
*
|
||||
@@ -322,28 +341,34 @@ namespace gridfire {
|
||||
double T9
|
||||
) const;
|
||||
|
||||
double calculateReverseRateTwoBody(
|
||||
[[nodiscard]] double calculateReverseRateTwoBody(
|
||||
const reaction::Reaction &reaction,
|
||||
const double T9,
|
||||
const double forwardRate,
|
||||
const double expFactor
|
||||
) const;
|
||||
|
||||
double calculateReverseRateTwoBodyDerivative(
|
||||
[[nodiscard]] double calculateReverseRateTwoBodyDerivative(
|
||||
const reaction::Reaction &reaction,
|
||||
const double T9,
|
||||
const double reverseRate
|
||||
) const;
|
||||
|
||||
bool isUsingReverseReactions() const;
|
||||
[[nodiscard]] bool isUsingReverseReactions() const;
|
||||
|
||||
void setUseReverseReactions(bool useReverse);
|
||||
|
||||
int getSpeciesIndex(
|
||||
[[nodiscard]] int getSpeciesIndex(
|
||||
const fourdst::atomic::Species& species
|
||||
) const override;
|
||||
|
||||
std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const override;
|
||||
[[nodiscard]] std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const override;
|
||||
|
||||
[[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
|
||||
|
||||
[[nodiscard]] BuildDepthType getDepth() const override;
|
||||
|
||||
void rebuild(const fourdst::composition::Composition& comp, const BuildDepthType depth) override;
|
||||
|
||||
|
||||
|
||||
@@ -427,6 +452,8 @@ namespace gridfire {
|
||||
boost::numeric::ublas::compressed_matrix<double> m_jacobianMatrix; ///< Jacobian matrix (species x species).
|
||||
|
||||
CppAD::ADFun<double> m_rhsADFun; ///< CppAD function for the right-hand side of the ODE.
|
||||
CppAD::sparse_jac_work m_jac_work; ///< Work object for sparse Jacobian calculations.
|
||||
CppAD::sparse_rc<std::vector<size_t>> m_full_jacobian_sparsity_pattern; ///< Full sparsity pattern for the Jacobian matrix.
|
||||
std::vector<std::unique_ptr<AtomicReverseRate>> m_atomicReverseRates;
|
||||
|
||||
screening::ScreeningType m_screeningType = screening::ScreeningType::BARE; ///< Screening type for the reaction network. Default to no screening.
|
||||
@@ -436,6 +463,8 @@ namespace gridfire {
|
||||
|
||||
bool m_useReverseReactions = true; ///< Flag to enable or disable reverse reactions. If false, only forward reactions are considered.
|
||||
|
||||
BuildDepthType m_depth;
|
||||
|
||||
std::vector<PrecomputedReaction> m_precomputedReactions; ///< Precomputed reactions for efficiency.
|
||||
std::unique_ptr<partition::PartitionFunction> m_partitionFunction; ///< Partition function for the network.
|
||||
|
||||
@@ -636,6 +665,14 @@ namespace gridfire {
|
||||
if (!m_useReverseReactions) {
|
||||
return static_cast<T>(0.0); // If reverse reactions are not used, return zero
|
||||
}
|
||||
s_debug = false;
|
||||
if (reaction.peName() == "p(p,e+)d" || reaction.peName() =="d(d,n)he3" || reaction.peName() == "c12(p,g)n13") {
|
||||
if constexpr (!std::is_same_v<T, ADDouble>) {
|
||||
s_debug = true;
|
||||
std::cout << "Calculating reverse molar flow for reaction: " << reaction.peName() << std::endl;
|
||||
std::cout << "\tT9: " << T9 << ", rho: " << rho << std::endl;
|
||||
}
|
||||
}
|
||||
T reverseMolarFlow = static_cast<T>(0.0);
|
||||
|
||||
if (reaction.qValue() != 0.0) {
|
||||
@@ -655,6 +692,9 @@ namespace gridfire {
|
||||
}
|
||||
} else {
|
||||
// A,B If not calling with an AD type, calculate the reverse rate directly
|
||||
if (s_debug) {
|
||||
std::cout << "\tUsing double overload\n";
|
||||
}
|
||||
reverseRateConstant = calculateReverseRate(reaction, T9);
|
||||
}
|
||||
|
||||
@@ -673,7 +713,7 @@ namespace gridfire {
|
||||
// E. Calculate the abundance term
|
||||
T productAbundanceTerm = static_cast<T>(1.0);
|
||||
for (const auto& [species, count] : productCounts) {
|
||||
const int speciesIndex = m_speciesToIndexMap.at(species);
|
||||
const unsigned long speciesIndex = m_speciesToIndexMap.at(species);
|
||||
productAbundanceTerm *= CppAD::pow(Y[speciesIndex], count);
|
||||
}
|
||||
|
||||
@@ -757,7 +797,7 @@ namespace gridfire {
|
||||
ss << "Forward: " << forwardMolarReactionFlow
|
||||
<< ", Reverse: " << reverseMolarFlow
|
||||
<< ", Net: " << molarReactionFlow;
|
||||
LOG_DEBUG(
|
||||
LOG_TRACE_L2(
|
||||
m_logger,
|
||||
"Reaction: {}, {}",
|
||||
reaction.peName(),
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
//
|
||||
// Created by Emily Boudreaux on 7/14/25.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef CONSTRUCTION_H
|
||||
#define CONSTRUCTION_H
|
||||
#include "gridfire/reaction/reaction.h"
|
||||
#include "gridfire/engine/types/building.h"
|
||||
|
||||
#endif //CONSTRUCTION_H
|
||||
#include "fourdst/composition/composition.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace gridfire {
|
||||
|
||||
reaction::LogicalReactionSet build_reaclib_nuclear_network(
|
||||
const fourdst::composition::Composition &composition,
|
||||
BuildDepthType maxLayers = NetworkBuildDepth::Full,
|
||||
bool reverse = false
|
||||
);
|
||||
}
|
||||
@@ -6,9 +6,15 @@
|
||||
#include "fourdst/composition/composition.h"
|
||||
#include "fourdst/composition/atomicSpecies.h"
|
||||
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace gridfire {
|
||||
fourdst::composition::Composition primeNetwork(
|
||||
|
||||
|
||||
PrimingReport primeNetwork(
|
||||
const NetIn&,
|
||||
DynamicEngine& engine
|
||||
);
|
||||
|
||||
16
src/network/include/gridfire/engine/types/building.h
Normal file
16
src/network/include/gridfire/engine/types/building.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace gridfire {
|
||||
enum class NetworkBuildDepth {
|
||||
Full = -1,
|
||||
Shallow = 1,
|
||||
SecondOrder = 2,
|
||||
ThirdOrder = 3,
|
||||
FourthOrder = 4,
|
||||
FifthOrder = 5
|
||||
};
|
||||
|
||||
using BuildDepthType = std::variant<NetworkBuildDepth, int>;
|
||||
}
|
||||
@@ -1,8 +1,42 @@
|
||||
//
|
||||
// Created by Emily Boudreaux on 7/14/25.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#ifndef REPORTING_H
|
||||
#define REPORTING_H
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <ranges>
|
||||
|
||||
#endif //REPORTING_H
|
||||
namespace gridfire {
|
||||
enum class PrimingReportStatus {
|
||||
FULL_SUCCESS = 0,
|
||||
NO_SPECIES_TO_PRIME = 1,
|
||||
MAX_ITERATIONS_REACHED = 2,
|
||||
FAILED_TO_FINALIZE_COMPOSITION = 3,
|
||||
FAILED_TO_FIND_CREATION_CHANNEL = 4,
|
||||
FAILED_TO_FIND_PRIMING_REACTIONS = 5,
|
||||
BASE_NETWORK_TOO_SHALLOW = 6
|
||||
};
|
||||
|
||||
inline std::map<PrimingReportStatus, std::string> PrimingReportStatusStrings = {
|
||||
{PrimingReportStatus::FULL_SUCCESS, "Full Success"},
|
||||
{PrimingReportStatus::NO_SPECIES_TO_PRIME, "No Species to Prime"},
|
||||
{PrimingReportStatus::MAX_ITERATIONS_REACHED, "Max Iterations Reached"},
|
||||
{PrimingReportStatus::FAILED_TO_FINALIZE_COMPOSITION, "Failed to Finalize Composition"},
|
||||
{PrimingReportStatus::FAILED_TO_FIND_CREATION_CHANNEL, "Failed to Find Creation Channel"},
|
||||
{PrimingReportStatus::FAILED_TO_FIND_PRIMING_REACTIONS, "Failed to Find Priming Reactions"},
|
||||
{PrimingReportStatus::BASE_NETWORK_TOO_SHALLOW, "Base Network Too Shallow"}
|
||||
};
|
||||
|
||||
struct PrimingReport {
|
||||
fourdst::composition::Composition primedComposition;
|
||||
std::vector<std::pair<fourdst::atomic::Species, double>> massFractionChanges; ///< Species and their destruction/creation rates
|
||||
bool success;
|
||||
PrimingReportStatus status;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const PrimingReport& report) {
|
||||
std::stringstream ss;
|
||||
std::string successStr = report.success ? "true" : "false";
|
||||
ss << "PrimingReport(success=" << successStr
|
||||
<< ", status=" << PrimingReportStatusStrings[report.status] << ")";
|
||||
return os << ss.str();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,9 @@
|
||||
#include "fourdst/config/config.h"
|
||||
#include "fourdst/logging/logging.h"
|
||||
|
||||
#include "gridfire/engine/procedures/priming.h"
|
||||
#include "gridfire/engine/procedures/construction.h"
|
||||
|
||||
#include "quill/Logger.h"
|
||||
|
||||
namespace gridfire {
|
||||
@@ -260,6 +263,8 @@ namespace gridfire {
|
||||
[[nodiscard]] int getSpeciesIndex(const fourdst::atomic::Species &species) const override;
|
||||
|
||||
[[nodiscard]] std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const override;
|
||||
|
||||
[[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
|
||||
private:
|
||||
using Config = fourdst::config::Config;
|
||||
using LogManager = fourdst::logging::LogManager;
|
||||
|
||||
@@ -161,6 +161,8 @@ namespace gridfire{
|
||||
[[nodiscard]] int getSpeciesIndex(const fourdst::atomic::Species &species) const override;
|
||||
|
||||
[[nodiscard]] std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const override;
|
||||
|
||||
[[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
|
||||
protected:
|
||||
bool m_isStale = true;
|
||||
DynamicEngine& m_baseEngine;
|
||||
|
||||
@@ -83,18 +83,20 @@ namespace gridfire {
|
||||
|
||||
[[nodiscard]] std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const override;
|
||||
|
||||
std::vector<fourdst::atomic::Species> getFastSpecies() const;
|
||||
const std::vector<fourdst::atomic::Species>& getDynamicSpecies() const;
|
||||
[[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
|
||||
|
||||
void equilibrateNetwork(
|
||||
const std::vector<double>& Y,
|
||||
[[nodiscard]] std::vector<fourdst::atomic::Species> getFastSpecies() const;
|
||||
[[nodiscard]] const std::vector<fourdst::atomic::Species>& getDynamicSpecies() const;
|
||||
|
||||
fourdst::composition::Composition equilibrateNetwork(
|
||||
const std::vector<double> &Y,
|
||||
double T9,
|
||||
double rho,
|
||||
double dt_control
|
||||
);
|
||||
|
||||
void equilibrateNetwork(
|
||||
const NetIn& netIn,
|
||||
fourdst::composition::Composition equilibrateNetwork(
|
||||
const NetIn &netIn,
|
||||
const double dt_control
|
||||
);
|
||||
|
||||
@@ -137,8 +139,8 @@ namespace gridfire {
|
||||
m_rho(rho),
|
||||
m_Y_scale(Y_scale) {}
|
||||
|
||||
int values() const { return m_qse_solve_indices.size(); }
|
||||
int inputs() const { return m_qse_solve_indices.size(); }
|
||||
[[nodiscard]] int values() const { return m_qse_solve_indices.size(); }
|
||||
[[nodiscard]] int inputs() const { return m_qse_solve_indices.size(); }
|
||||
|
||||
int operator()(const InputType& v_qse, OutputType& f_qse) const;
|
||||
int df(const InputType& v_qse, JacobianType& J_qse) const;
|
||||
|
||||
@@ -20,13 +20,10 @@ namespace gridfire {
|
||||
public:
|
||||
NetworkPrimingEngineView(const std::string& primingSymbol, DynamicEngine& baseEngine);
|
||||
NetworkPrimingEngineView(const fourdst::atomic::Species& primingSpecies, DynamicEngine& baseEngine);
|
||||
const std::vector<std::string>& getPrimingReactionNames() const { return m_peNames; }
|
||||
const fourdst::atomic::Species& getPrimingSpecies() const { return m_primingSpecies; }
|
||||
|
||||
|
||||
private:
|
||||
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
|
||||
std::vector<std::string> m_peNames; ///< Names of the priming reactions.
|
||||
fourdst::atomic::Species m_primingSpecies; ///< The priming species, if specified.
|
||||
private:
|
||||
std::vector<std::string> constructPrimingReactionSet(
|
||||
|
||||
@@ -104,7 +104,5 @@ namespace gridfire {
|
||||
};
|
||||
|
||||
|
||||
reaction::LogicalReactionSet build_reaclib_nuclear_network(const fourdst::composition::Composition &composition, bool reverse);
|
||||
|
||||
|
||||
} // namespace nuclearNetwork
|
||||
|
||||
Reference in New Issue
Block a user