docs(ridfire)
Added more documentation, also moved all engine code into gridfire::engine namespace to be more in line with other parts of teh code base
This commit is contained in:
@@ -5,17 +5,17 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace gridfire::diagnostics {
|
||||
void report_limiting_species(
|
||||
const DynamicEngine& engine,
|
||||
const std::vector<double>& Y_full,
|
||||
const std::vector<double>& E_full,
|
||||
namespace gridfire::engine::diagnostics {
|
||||
std::optional<nlohmann::json> report_limiting_species(
|
||||
const DynamicEngine &engine,
|
||||
const std::vector<double> &Y_full,
|
||||
const std::vector<double> &E_full,
|
||||
const double relTol,
|
||||
const double absTol,
|
||||
const size_t top_n
|
||||
const size_t top_n,
|
||||
bool json
|
||||
) {
|
||||
struct SpeciesError {
|
||||
std::string name;
|
||||
@@ -66,15 +66,21 @@ namespace gridfire::diagnostics {
|
||||
columns.push_back(std::make_unique<utils::Column<double>>("Abundance", sorted_abundances));
|
||||
columns.push_back(std::make_unique<utils::Column<double>>("Error", sorted_errors));
|
||||
|
||||
std::cout << utils::format_table("Timestep Limiting Species", columns) << std::endl;
|
||||
if (json) {
|
||||
return utils::to_json(columns);
|
||||
}
|
||||
|
||||
utils::print_table("Timestep Limiting Species", columns);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void inspect_species_balance(
|
||||
std::optional<nlohmann::json> inspect_species_balance(
|
||||
const DynamicEngine& engine,
|
||||
const std::string& species_name,
|
||||
const fourdst::composition::Composition &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
const double rho,
|
||||
bool json
|
||||
) {
|
||||
const auto& species_obj = fourdst::atomic::species.at(species_name);
|
||||
|
||||
@@ -103,12 +109,18 @@ namespace gridfire::diagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
nlohmann::json j;
|
||||
{
|
||||
std::vector<std::unique_ptr<utils::ColumnBase>> columns;
|
||||
columns.push_back(std::make_unique<utils::Column<std::string>>("Reaction ID", creation_ids));
|
||||
columns.push_back(std::make_unique<utils::Column<int>>("Stoichiometry", creation_stoichiometry));
|
||||
columns.push_back(std::make_unique<utils::Column<double>>("Molar Flow", creation_flows));
|
||||
std::cout << utils::format_table("Creation Reactions for " + species_name, columns) << std::endl;
|
||||
if (json) {
|
||||
j["Creation_Reactions_" + species_name] = utils::to_json(columns);
|
||||
}
|
||||
else {
|
||||
utils::print_table("Creation Reactions for " + species_name, columns);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -116,43 +128,44 @@ namespace gridfire::diagnostics {
|
||||
columns.push_back(std::make_unique<utils::Column<std::string>>("Reaction ID", destruction_ids));
|
||||
columns.push_back(std::make_unique<utils::Column<int>>("Stoichiometry", destruction_stoichiometry));
|
||||
columns.push_back(std::make_unique<utils::Column<double>>("Molar Flow", destruction_flows));
|
||||
std::cout << utils::format_table("Destruction Reactions for " + species_name, columns) << std::endl;
|
||||
if (json) {
|
||||
j["Destruction_Reactions_" + species_name] = utils::to_json(columns);
|
||||
} else {
|
||||
utils::print_table("Destruction Reactions for " + species_name, columns);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "--- Balance Summary for " << species_name << " ---" << std::endl;
|
||||
std::cout << " Total Creation Rate: " << std::scientific << total_creation_flow << " [mol/g/s]" << std::endl;
|
||||
std::cout << " Total Destruction Rate: " << std::scientific << total_destruction_flow << " [mol/g/s]" << std::endl;
|
||||
std::cout << " Net dY/dt: " << std::scientific << (total_creation_flow - total_destruction_flow) << std::endl;
|
||||
std::cout << "-----------------------------------" << std::endl;
|
||||
std::vector<std::unique_ptr<utils::ColumnBase>> summary_columns;
|
||||
summary_columns.push_back(std::make_unique<utils::Column<std::string>>("Metric", std::vector<std::string>{
|
||||
"Total Creation Rate [mol/g/s]",
|
||||
"Total Destruction Rate [mol/g/s]",
|
||||
"Net dY/dt [mol/g/s]"
|
||||
}));
|
||||
summary_columns.push_back(std::make_unique<utils::Column<double>>("Value", std::vector<double>{
|
||||
total_creation_flow,
|
||||
total_destruction_flow,
|
||||
total_creation_flow - total_destruction_flow
|
||||
}));
|
||||
|
||||
if (json) {
|
||||
j["Species_Balance_Summary_" + species_name] = utils::to_json(summary_columns);
|
||||
return j;
|
||||
}
|
||||
|
||||
utils::print_table("Species Balance Summary for " + species_name, summary_columns);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void inspect_jacobian_stiffness(
|
||||
std::optional<nlohmann::json> inspect_jacobian_stiffness(
|
||||
const DynamicEngine &engine,
|
||||
const fourdst::composition::Composition &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
) {
|
||||
inspect_jacobian_stiffness(engine, comp, T9, rho, false, std::nullopt);
|
||||
}
|
||||
|
||||
|
||||
void inspect_jacobian_stiffness(
|
||||
const DynamicEngine& engine,
|
||||
const fourdst::composition::Composition &comp,
|
||||
const double T9,
|
||||
const double rho,
|
||||
const bool save,
|
||||
const std::optional<std::string> &filename
|
||||
const bool json
|
||||
) {
|
||||
NetworkJacobian jac = engine.generateJacobianMatrix(comp, T9, rho);
|
||||
|
||||
jac = regularize_jacobian(jac, comp);
|
||||
if (save) {
|
||||
if (!filename.has_value()) {
|
||||
throw std::invalid_argument("Filename must be provided when save is true.");
|
||||
}
|
||||
jac.to_csv(filename.value());
|
||||
}
|
||||
|
||||
const auto& species_list = engine.getNetworkSpecies();
|
||||
|
||||
@@ -172,16 +185,28 @@ namespace gridfire::diagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n--- Jacobian Stiffness Report ---" << std::endl;
|
||||
if (max_diag_species.has_value()) {
|
||||
std::cout << " Largest Diagonal Element (d(dYi/dt)/dYi): " << std::scientific << max_diag
|
||||
<< " for species " << max_diag_species->name() << std::endl;
|
||||
std::vector<std::unique_ptr<utils::ColumnBase>> jacobian_columns;
|
||||
jacobian_columns.push_back(std::make_unique<utils::Column<std::string>>("Metric", std::vector<std::string>{
|
||||
"Largest Diagonal Element (d(dYi/dt)/dYi)",
|
||||
"Largest Off-Diagonal Element (d(dYi/dt)/dYj)"
|
||||
}));
|
||||
jacobian_columns.push_back(std::make_unique<utils::Column<double>>("Value", std::vector<double>{
|
||||
max_diag,
|
||||
max_off_diag
|
||||
}));
|
||||
jacobian_columns.push_back(std::make_unique<utils::Column<std::string>>("Species", std::vector<std::string>{
|
||||
max_diag_species.has_value() ? std::string(max_diag_species->name()) : "N/A",
|
||||
max_off_diag_species.has_value() ?
|
||||
("d(" + std::string(max_off_diag_species->first.name()) + ")/d(" + std::string(max_off_diag_species->second.name()) + ")")
|
||||
: "N/A"
|
||||
}));
|
||||
|
||||
if (json) {
|
||||
nlohmann::json j;
|
||||
j["Jacobian_Stiffness"] = utils::to_json(jacobian_columns);
|
||||
return j;
|
||||
}
|
||||
if (max_off_diag_species.has_value()) {
|
||||
std::cout << " Largest Off-Diagonal Element (d(dYi/dt)/dYj): " << std::scientific << max_off_diag
|
||||
<< " for d(" << max_off_diag_species->first.name()
|
||||
<< ")/d(" << max_off_diag_species->second.name() << ")" << std::endl;
|
||||
}
|
||||
std::cout << "---------------------------------" << std::endl;
|
||||
utils::print_table("Jacobian Stiffness Diagnostics", jacobian_columns);
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "gridfire/engine/engine_graph.h"
|
||||
#include "gridfire/reaction/reaction.h"
|
||||
#include "gridfire/network.h"
|
||||
#include "gridfire/types/types.h"
|
||||
#include "gridfire/screening/screening_types.h"
|
||||
#include "gridfire/engine/procedures/priming.h"
|
||||
#include "gridfire/partition/partition_ground.h"
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "cppad/utility/sparse_rcv.hpp"
|
||||
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
GraphEngine::GraphEngine(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const BuildDepthType buildDepth
|
||||
@@ -66,7 +66,7 @@ namespace gridfire {
|
||||
syncInternalMaps();
|
||||
}
|
||||
|
||||
std::expected<StepDerivatives<double>, expectations::StaleEngineError> GraphEngine::calculateRHSAndEnergy(
|
||||
std::expected<StepDerivatives<double>, EngineStatus> GraphEngine::calculateRHSAndEnergy(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -74,17 +74,17 @@ namespace gridfire {
|
||||
return calculateRHSAndEnergy(comp, T9, rho, m_reactions);
|
||||
}
|
||||
|
||||
std::expected<StepDerivatives<double>, expectations::StaleEngineError> GraphEngine::calculateRHSAndEnergy(
|
||||
std::expected<StepDerivatives<double>, EngineStatus> GraphEngine::calculateRHSAndEnergy(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho,
|
||||
const reaction::ReactionSet &activeReactions
|
||||
) const {
|
||||
LOG_TRACE_L2(m_logger, "Calculating RHS and Energy in GraphEngine at T9 = {}, rho = {}.", T9, rho);
|
||||
LOG_TRACE_L3(m_logger, "Calculating RHS and Energy in GraphEngine at T9 = {}, rho = {}.", T9, rho);
|
||||
const double Ye = comp.getElectronAbundance();
|
||||
const double mue = 0.0; // TODO: Remove
|
||||
if (m_usePrecomputation) {
|
||||
LOG_TRACE_L2(m_logger, "Using precomputation for reaction rates in GraphEngine calculateRHSAndEnergy.");
|
||||
LOG_TRACE_L3(m_logger, "Using precomputation for reaction rates in GraphEngine calculateRHSAndEnergy.");
|
||||
std::vector<double> bare_rates;
|
||||
std::vector<double> bare_reverse_rates;
|
||||
bare_rates.reserve(activeReactions.size());
|
||||
@@ -98,7 +98,7 @@ namespace gridfire {
|
||||
}
|
||||
}
|
||||
|
||||
LOG_TRACE_L2(m_logger, "Precomputed {} forward and {} reverse reaction rates for active reactions.", bare_rates.size(), bare_reverse_rates.size());
|
||||
LOG_TRACE_L3(m_logger, "Precomputed {} forward and {} reverse reaction rates for active reactions.", bare_rates.size(), bare_reverse_rates.size());
|
||||
|
||||
// --- The public facing interface can always use the precomputed version since taping is done internally ---
|
||||
return calculateAllDerivativesUsingPrecomputation(comp, bare_rates, bare_reverse_rates, T9, rho, activeReactions);
|
||||
@@ -543,6 +543,15 @@ namespace gridfire {
|
||||
fullNetIn.temperature = netIn.temperature;
|
||||
fullNetIn.density = netIn.density;
|
||||
|
||||
// Short circuit path if already primed
|
||||
// if (m_has_been_primed) {
|
||||
// PrimingReport report;
|
||||
// report.primedComposition = composition;
|
||||
// report.success = true;
|
||||
// report.status = PrimingReportStatus::ALREADY_PRIMED;
|
||||
// return report;
|
||||
// }
|
||||
|
||||
std::optional<std::vector<reaction::ReactionType>> reactionTypesToIgnore = std::nullopt;
|
||||
if (!m_useReverseReactions) {
|
||||
reactionTypesToIgnore = {reaction::ReactionType::WEAK};
|
||||
@@ -550,6 +559,7 @@ namespace gridfire {
|
||||
|
||||
auto primingReport = primeNetwork(fullNetIn, *this, reactionTypesToIgnore);
|
||||
|
||||
m_has_been_primed = true;
|
||||
return primingReport;
|
||||
}
|
||||
|
||||
@@ -603,7 +613,7 @@ namespace gridfire {
|
||||
const double rho,
|
||||
const reaction::ReactionSet &activeReactions
|
||||
) const {
|
||||
LOG_TRACE_L2(m_logger, "Computing screening factors for {} active reactions.", activeReactions.size());
|
||||
LOG_TRACE_L3(m_logger, "Computing screening factors for {} active reactions.", activeReactions.size());
|
||||
// --- Calculate screening factors ---
|
||||
const std::vector<double> screeningFactors = m_screeningModel->calculateScreeningFactors(
|
||||
activeReactions,
|
||||
@@ -636,6 +646,11 @@ namespace gridfire {
|
||||
forwardAbundanceProduct = 0.0;
|
||||
break; // No need to continue if one of the reactants has zero abundance
|
||||
}
|
||||
double factor = std::pow(comp.getMolarAbundance(reactant), power);
|
||||
if (!std::isfinite(factor)) {
|
||||
LOG_CRITICAL(m_logger, "Non-finite factor encountered in forward abundance product for reaction '{}'. Check input abundances for validity.", reaction->id());
|
||||
throw exceptions::BadRHSEngineError("Non-finite factor encountered in forward abundance product.");
|
||||
}
|
||||
forwardAbundanceProduct *= std::pow(comp.getMolarAbundance(reactant), power);
|
||||
}
|
||||
|
||||
@@ -652,7 +667,10 @@ namespace gridfire {
|
||||
precomputedReaction.symmetry_factor *
|
||||
forwardAbundanceProduct *
|
||||
std::pow(rho, numReactants > 1 ? static_cast<double>(numReactants) - 1 : 0.0);
|
||||
|
||||
if (!std::isfinite(forwardMolarReactionFlow)) {
|
||||
LOG_CRITICAL(m_logger, "Non-finite forward molar reaction flow computed for reaction '{}'. Check input abundances and rates for validity.", reaction->id());
|
||||
throw exceptions::BadRHSEngineError("Non-finite forward molar reaction flow computed.");
|
||||
}
|
||||
|
||||
// --- Reverse reaction flow ---
|
||||
// Only do this is the reaction has a non-zero reverse symmetry factor (i.e. is reversible)
|
||||
@@ -678,7 +696,7 @@ namespace gridfire {
|
||||
reactionCounter++;
|
||||
}
|
||||
|
||||
LOG_TRACE_L2(m_logger, "Computed {} molar reaction flows for active reactions. Assembling these into RHS", molarReactionFlows.size());
|
||||
LOG_TRACE_L3(m_logger, "Computed {} molar reaction flows for active reactions. Assembling these into RHS", molarReactionFlows.size());
|
||||
|
||||
// --- Assemble molar abundance derivatives ---
|
||||
StepDerivatives<double> result;
|
||||
@@ -860,10 +878,6 @@ namespace gridfire {
|
||||
for (size_t j = 0; j < numSpecies; ++j) {
|
||||
double value = dotY[i * (numSpecies + 2) + j];
|
||||
if (std::abs(value) > MIN_JACOBIAN_THRESHOLD || i == j) { // Always keep diagonal elements to avoid pathological stiffness
|
||||
if (i == j && value == 0) {
|
||||
LOG_WARNING(m_logger, "While generating the Jacobian matrix, a zero diagonal element was encountered at index ({}, {}) (species: {}, abundance: {}). This may lead to numerical instability. Setting to -1 to avoid singularity", i, j, m_networkSpecies[i].name(), adInput[i]);
|
||||
// value = -1.0;
|
||||
}
|
||||
triplets.emplace_back(i, j, value);
|
||||
}
|
||||
}
|
||||
@@ -966,7 +980,7 @@ namespace gridfire {
|
||||
|
||||
CppAD::sparse_rcv<std::vector<size_t>, std::vector<double>> jac_subset(CppAD_sparsity_pattern);
|
||||
|
||||
// PERF: one of *the* most pressing things that needs to be done is remove the nead for this call every
|
||||
// PERF: one of *the* most pressing things that needs to be done is remove the need for this call every
|
||||
// time the jacobian is needed since coloring is expensive and we are throwing away the caching
|
||||
// power of CppAD by clearing the work vector each time. We do this since we make a new subset every
|
||||
// time. However, a better solution would be to make the subset stateful so it only changes if the requested
|
||||
@@ -1100,7 +1114,7 @@ namespace gridfire {
|
||||
LOG_TRACE_L1(m_logger, "Successfully exported network graph to {}", filename);
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> GraphEngine::getSpeciesTimescales(
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, EngineStatus> GraphEngine::getSpeciesTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -1108,7 +1122,7 @@ namespace gridfire {
|
||||
return getSpeciesTimescales(comp, T9, rho, m_reactions);
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> GraphEngine::getSpeciesTimescales(
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, EngineStatus> GraphEngine::getSpeciesTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho,
|
||||
@@ -1144,7 +1158,7 @@ namespace gridfire {
|
||||
return speciesTimescales;
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> GraphEngine::getSpeciesDestructionTimescales(
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, EngineStatus> GraphEngine::getSpeciesDestructionTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -1152,7 +1166,7 @@ namespace gridfire {
|
||||
return getSpeciesDestructionTimescales(comp, T9, rho, m_reactions);
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> GraphEngine::getSpeciesDestructionTimescales(
|
||||
std::expected<std::unordered_map<fourdst::atomic::Species, double>, EngineStatus> GraphEngine::getSpeciesDestructionTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho,
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
#include "quill/LogMacros.h"
|
||||
namespace {
|
||||
// Simple heuristic to check if a reaclib reaction is a strong or weak reaction
|
||||
/* A weak reaction is defined here as one where:
|
||||
- The number of reactants is equal to the number of products
|
||||
- There is only one reactant and one product
|
||||
- The mass number (A) of the reactant is equal to the mass number (A) of the product
|
||||
*/
|
||||
bool reaclib_reaction_is_weak(const gridfire::reaction::Reaction& reaction) {
|
||||
const std::vector<fourdst::atomic::Species>& reactants = reaction.reactants();
|
||||
const std::vector<fourdst::atomic::Species>& products = reaction.products();
|
||||
@@ -41,10 +46,10 @@ namespace {
|
||||
|
||||
gridfire::reaction::ReactionSet register_weak_reactions(
|
||||
const gridfire::rates::weak::WeakRateInterpolator &weakInterpolator,
|
||||
const gridfire::NetworkConstructionFlags reactionTypes
|
||||
const gridfire::engine::NetworkConstructionFlags reactionTypes
|
||||
) {
|
||||
gridfire::reaction::ReactionSet weak_reaction_pool;
|
||||
if (!has_flag(reactionTypes, gridfire::NetworkConstructionFlags::WRL_WEAK)) {
|
||||
if (!has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::WRL_WEAK)) {
|
||||
return weak_reaction_pool;
|
||||
}
|
||||
|
||||
@@ -58,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::NetworkConstructionFlags::BETA_PLUS)) {
|
||||
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::BETA_PLUS)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
@@ -67,7 +72,7 @@ namespace {
|
||||
)
|
||||
);
|
||||
}
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::ELECTRON_CAPTURE)) {
|
||||
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::ELECTRON_CAPTURE)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
@@ -78,7 +83,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
if (upProduct.has_value()) { // Only add the reaction if the Species map contains the product
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::BETA_MINUS)) {
|
||||
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::BETA_MINUS)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
@@ -87,7 +92,7 @@ namespace {
|
||||
)
|
||||
);
|
||||
}
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::POSITRON_CAPTURE)) {
|
||||
if (has_flag(reactionTypes, gridfire::engine::NetworkConstructionFlags::POSITRON_CAPTURE)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
@@ -103,14 +108,14 @@ namespace {
|
||||
}
|
||||
|
||||
gridfire::reaction::ReactionSet register_strong_reactions(
|
||||
const gridfire::NetworkConstructionFlags reaction_types
|
||||
const gridfire::engine::NetworkConstructionFlags reaction_types
|
||||
) {
|
||||
gridfire::reaction::ReactionSet strong_reaction_pool;
|
||||
if (has_flag(reaction_types, gridfire::NetworkConstructionFlags::STRONG)) {
|
||||
if (has_flag(reaction_types, gridfire::engine::NetworkConstructionFlags::STRONG)) {
|
||||
const auto& allReaclibReactions = gridfire::reaclib::get_all_reaclib_reactions();
|
||||
for (const auto& reaction : allReaclibReactions) {
|
||||
const bool isWeakReaction = reaclib_reaction_is_weak(*reaction);
|
||||
const bool okayToUseReaclibWeakReaction = has_flag(reaction_types, gridfire::NetworkConstructionFlags::REACLIB_WEAK);
|
||||
const bool okayToUseReaclibWeakReaction = has_flag(reaction_types, gridfire::engine::NetworkConstructionFlags::REACLIB_WEAK);
|
||||
|
||||
const bool reaclibWeakOkay = !isWeakReaction || okayToUseReaclibWeakReaction;
|
||||
if (!reaction->is_reverse() && reaclibWeakOkay) {
|
||||
@@ -121,17 +126,17 @@ namespace {
|
||||
return strong_reaction_pool;
|
||||
}
|
||||
|
||||
bool validate_unique_weak_set(gridfire::NetworkConstructionFlags flag) {
|
||||
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::NetworkConstructionFlags, 4> WRL_Flags = {
|
||||
gridfire::NetworkConstructionFlags::BETA_PLUS,
|
||||
gridfire::NetworkConstructionFlags::ELECTRON_CAPTURE,
|
||||
gridfire::NetworkConstructionFlags::POSITRON_CAPTURE,
|
||||
gridfire::NetworkConstructionFlags::BETA_MINUS
|
||||
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
|
||||
};
|
||||
|
||||
if (!has_flag(flag, gridfire::NetworkConstructionFlags::REACLIB_WEAK)) {
|
||||
if (!has_flag(flag, gridfire::engine::NetworkConstructionFlags::REACLIB_WEAK)) {
|
||||
return true;
|
||||
}
|
||||
for (const auto& WRLReactionType : WRL_Flags) {
|
||||
@@ -143,7 +148,7 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
using reaction::ReactionSet;
|
||||
using reaction::Reaction;
|
||||
using fourdst::atomic::Species;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "gridfire/solver/solver.h"
|
||||
|
||||
#include "gridfire/engine/engine_abstract.h"
|
||||
#include "gridfire/network.h"
|
||||
#include "gridfire/types/types.h"
|
||||
#include "gridfire/exceptions/error_solver.h"
|
||||
|
||||
#include "fourdst/logging/logging.h"
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "quill/LogMacros.h"
|
||||
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
using fourdst::composition::Composition;
|
||||
using fourdst::atomic::Species;
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace gridfire {
|
||||
) {
|
||||
const auto logger = LogManager::getInstance().getLogger("log");
|
||||
solver::CVODESolverStrategy integrator(engine);
|
||||
|
||||
// Do not need high precision for priming
|
||||
integrator.set_absTol(1e-3);
|
||||
integrator.set_relTol(1e-3);
|
||||
|
||||
integrator.set_stdout_logging_enabled(false);
|
||||
NetIn solverInput(netIn);
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#include "quill/LogMacros.h"
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
NetworkJacobian::NetworkJacobian(
|
||||
const Eigen::SparseMatrix<double>& jacobianMatrix,
|
||||
const std::function<fourdst::atomic::Species(size_t)> &indexToSpeciesFunc
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
#include "gridfire/network.h"
|
||||
#include "gridfire/types/types.h"
|
||||
#include "gridfire/exceptions/error_engine.h"
|
||||
|
||||
#include "quill/LogMacros.h"
|
||||
#include "quill/Logger.h"
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
using fourdst::atomic::Species;
|
||||
AdaptiveEngineView::AdaptiveEngineView(
|
||||
DynamicEngine &baseEngine
|
||||
@@ -77,7 +77,7 @@ namespace gridfire {
|
||||
return m_activeSpecies;
|
||||
}
|
||||
|
||||
std::expected<StepDerivatives<double>, expectations::StaleEngineError> AdaptiveEngineView::calculateRHSAndEnergy(
|
||||
std::expected<StepDerivatives<double>, EngineStatus> AdaptiveEngineView::calculateRHSAndEnergy(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -205,7 +205,7 @@ namespace gridfire {
|
||||
throw exceptions::UnableToSetNetworkReactionsError("AdaptiveEngineView does not support setting network reactions directly. Use update() with NetIn instead. Perhaps you meant to call this on the base engine?");
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<Species, double>, expectations::StaleEngineError> AdaptiveEngineView::getSpeciesTimescales(
|
||||
std::expected<std::unordered_map<Species, double>, EngineStatus> AdaptiveEngineView::getSpeciesTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -231,8 +231,7 @@ namespace gridfire {
|
||||
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<Species, double>, expectations::StaleEngineError>
|
||||
AdaptiveEngineView::getSpeciesDestructionTimescales(
|
||||
std::expected<std::unordered_map<Species, double>, EngineStatus> AdaptiveEngineView::getSpeciesDestructionTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -357,7 +356,7 @@ namespace gridfire {
|
||||
if (!reachable.contains(species)) {
|
||||
to_vist.push(species);
|
||||
reachable.insert(species);
|
||||
LOG_TRACE_L2(m_logger, "Network Connectivity Analysis: Species '{}' is part of the initial fuel.", species.name());
|
||||
LOG_TRACE_L2(m_logger, "Network Connectivity Analysis: Species {:5} is part of the initial fuel", species.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,7 +377,7 @@ namespace gridfire {
|
||||
if (!reachable.contains(product)) {
|
||||
reachable.insert(product);
|
||||
new_species_found_in_pass = true;
|
||||
LOG_TRACE_L2(m_logger, "Network Connectivity Analysis: Species '{}' is reachable via reaction '{}'.", product.name(), reaction->id());
|
||||
LOG_TRACE_L2(m_logger, "Network Connectivity Analysis: Species {:5} is reachable via reaction {:20}", product.name(), reaction->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -397,19 +396,19 @@ namespace gridfire {
|
||||
LOG_TRACE_L1(m_logger, "Culling reactions based on flow rates...");
|
||||
const auto relative_culling_threshold = m_config.get<double>("gridfire:AdaptiveEngineView:RelativeCullingThreshold", 1e-75);
|
||||
double absoluteCullingThreshold = relative_culling_threshold * maxFlow;
|
||||
LOG_DEBUG(m_logger, "Relative culling threshold: {:0.3E} ({})", relative_culling_threshold, absoluteCullingThreshold);
|
||||
LOG_DEBUG(m_logger, "Relative culling threshold: {:7.3E} ({:7.3E})", relative_culling_threshold, absoluteCullingThreshold);
|
||||
std::vector<const reaction::Reaction*> culledReactions;
|
||||
for (const auto& [reactionPtr, flowRate]: allFlows) {
|
||||
bool keepReaction = false;
|
||||
if (flowRate > absoluteCullingThreshold) {
|
||||
LOG_TRACE_L2(m_logger, "Maintaining reaction '{}' with relative (abs) flow rate: {:0.3E} ({:0.3E} [mol/s])", reactionPtr->id(), flowRate/maxFlow, flowRate);
|
||||
LOG_TRACE_L2(m_logger, "Maintaining reaction '{:20}' with relative (abs) flow rate: {:7.3E} ({:7.3E} [mol/s])", reactionPtr->id(), flowRate/maxFlow, flowRate);
|
||||
keepReaction = true;
|
||||
} else {
|
||||
bool zero_flow_due_to_reachable_reactants = false;
|
||||
if (flowRate < 1e-99 && flowRate > 0.0) {
|
||||
for (const auto& reactant: reactionPtr->reactants()) {
|
||||
if (comp.getMolarAbundance(reactant) < 1e-99 && reachableSpecies.contains(reactant)) {
|
||||
LOG_TRACE_L1(m_logger, "Maintaining reaction '{}' with low flow ({:0.3E} [mol/s/g]) due to reachable reactant '{}'.", reactionPtr->id(), flowRate, reactant.name());
|
||||
LOG_TRACE_L1(m_logger, "Maintaining reaction {:20} with low flow ({:7.3E} [mol/s/g]) due to reachable reactant '{:6}'.", reactionPtr->id(), flowRate, reactant.name());
|
||||
zero_flow_due_to_reachable_reactants = true;
|
||||
break;
|
||||
}
|
||||
@@ -422,10 +421,10 @@ namespace gridfire {
|
||||
if (keepReaction) {
|
||||
culledReactions.push_back(reactionPtr);
|
||||
} else {
|
||||
LOG_TRACE_L1(m_logger, "Culling reaction '{}' due to low flow rate or lack of connectivity.", reactionPtr->id());
|
||||
LOG_TRACE_L1(m_logger, "Culling reaction '{:20}' due to low flow rate or lack of connectivity.", reactionPtr->id());
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(m_logger, "Selected {} (total: {}, culled: {}) reactions based on flow rates.", culledReactions.size(), allFlows.size(), allFlows.size() - culledReactions.size());
|
||||
LOG_DEBUG(m_logger, "Selected {:5} (total: {:5}, culled: {:5}) reactions based on flow rates.", culledReactions.size(), allFlows.size(), allFlows.size() - culledReactions.size());
|
||||
return culledReactions;
|
||||
}
|
||||
|
||||
@@ -438,8 +437,9 @@ namespace gridfire {
|
||||
) const {
|
||||
const auto result = m_baseEngine.getSpeciesTimescales(comp, T9, rho);
|
||||
if (!result) {
|
||||
LOG_ERROR(m_logger, "Failed to get species timescales due to stale engine state.");
|
||||
throw exceptions::StaleEngineError("Failed to get species timescales");
|
||||
LOG_CRITICAL(m_logger, "Failed to get species timescales due to base engine failure");
|
||||
m_logger->flush_log();
|
||||
throw exceptions::EngineError("Failed to get species timescales due base engine failure");
|
||||
}
|
||||
std::unordered_map<Species, double> timescales = result.value();
|
||||
std::set<Species> onlyProducedSpecies;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "fourdst/composition/exceptions/exceptions_composition.h"
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
using fourdst::atomic::Species;
|
||||
|
||||
DefinedEngineView::DefinedEngineView(
|
||||
@@ -40,7 +40,7 @@ namespace gridfire {
|
||||
return m_activeSpeciesVectorCache.value();
|
||||
}
|
||||
|
||||
std::expected<StepDerivatives<double>, expectations::StaleEngineError> DefinedEngineView::calculateRHSAndEnergy(
|
||||
std::expected<StepDerivatives<double>, EngineStatus> DefinedEngineView::calculateRHSAndEnergy(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -170,7 +170,7 @@ namespace gridfire {
|
||||
m_activeSpeciesVectorCache = std::nullopt; // Invalidate species vector cache
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<Species, double>, expectations::StaleEngineError> DefinedEngineView::getSpeciesTimescales(
|
||||
std::expected<std::unordered_map<Species, double>, EngineStatus> DefinedEngineView::getSpeciesTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
@@ -193,7 +193,7 @@ namespace gridfire {
|
||||
return definedTimescales;
|
||||
}
|
||||
|
||||
std::expected<std::unordered_map<Species, double>, expectations::StaleEngineError> DefinedEngineView::getSpeciesDestructionTimescales(
|
||||
std::expected<std::unordered_map<Species, double>, EngineStatus> DefinedEngineView::getSpeciesDestructionTimescales(
|
||||
const fourdst::composition::CompositionAbstract &comp,
|
||||
const double T9,
|
||||
const double rho
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace gridfire {
|
||||
namespace gridfire::engine {
|
||||
using fourdst::atomic::species;
|
||||
|
||||
NetworkPrimingEngineView::NetworkPrimingEngineView(
|
||||
|
||||
Reference in New Issue
Block a user