feat(solver): added CVODE solver from SUNDIALS

This commit is contained in:
2025-08-15 12:11:32 -04:00
parent 0b77f2e269
commit ed1c5a1ac7
16 changed files with 588 additions and 62 deletions

View File

@@ -48,7 +48,7 @@ namespace gridfire {
if (depth == static_cast<int>(NetworkBuildDepth::Full)) {
LOG_INFO(logger, "Building full nuclear network with a total of {} reactions.", allReactions.size());
const ReactionSet reactionSet(remainingReactions);
return reaction::packReactionSet(reactionSet);
return reactionSet;
}
std::unordered_set<Species> availableSpecies;
@@ -104,7 +104,7 @@ namespace gridfire {
LOG_INFO(logger, "Network construction completed with {} reactions collected.", collectedReactions.size());
const ReactionSet reactionSet(collectedReactions);
return reaction::packReactionSet(reactionSet);
return reactionSet;
}
}

View File

@@ -116,7 +116,7 @@ namespace gridfire {
LOG_TRACE_L3(logger, "Found equilibrium for {}: X_eq = {:.4e}", primingSpecies.name(), equilibriumMassFraction);
if (const reaction::Reaction* dominantChannel = findDominantCreationChannel(primer, primingSpecies, Y, T9, rho)) {
LOG_TRACE_L3(logger, "Dominant creation channel for {}: {}", primingSpecies.name(), dominantChannel->peName());
LOG_TRACE_L3(logger, "Dominant creation channel for {}: {}", primingSpecies.name(), dominantChannel->id());
double totalReactantMass = 0.0;
for (const auto& reactant : dominantChannel->reactants()) {
@@ -209,7 +209,7 @@ namespace gridfire {
double calculateCreationRate(
const DynamicEngine& engine,
const fourdst::atomic::Species& species,
const Species& species,
const std::vector<double>& Y,
const double T9,
const double rho
@@ -218,6 +218,8 @@ namespace gridfire {
for (const auto& reaction: engine.getNetworkReactions()) {
const int stoichiometry = reaction->stoichiometry(species);
if (stoichiometry > 0) {
if (engine.calculateMolarReactionFlow(*reaction, Y, T9, rho) > 0.0) {
}
creationRate += stoichiometry * engine.calculateMolarReactionFlow(*reaction, Y, T9, rho);
}
}

View File

@@ -385,7 +385,7 @@ namespace gridfire {
for (const auto& reaction : fullReactionSet) {
const double flow = m_baseEngine.calculateMolarReactionFlow(*reaction, out_Y_Full, T9, rho);
reactionFlows.push_back({reaction.get(), flow});
LOG_TRACE_L1(m_logger, "Reaction '{}' has flow rate: {:0.3E} [mol/s/g]", reaction.id(), flow);
LOG_TRACE_L1(m_logger, "Reaction '{}' has flow rate: {:0.3E} [mol/s/g]", reaction->id(), flow);
}
return reactionFlows;
}
@@ -423,7 +423,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 '{}' is reachable via reaction '{}'.", product.name(), reaction->id());
}
}
}

View File

@@ -358,7 +358,7 @@ namespace gridfire {
LOG_TRACE_L3(m_logger, "Active reactions: {}", [this]() -> std::string {
std::string result;
for (const auto& reaction : m_activeReactions) {
result += std::string(reaction.id()) + ", ";
result += std::string(reaction->id()) + ", ";
}
if (!result.empty()) {
result.pop_back(); // Remove last space

View File

@@ -1020,7 +1020,7 @@ namespace gridfire {
LOG_TRACE_L3(
m_logger,
"Reaction {} is internal to the group containing {} and contributes to internal flux by {}",
reaction.id(),
reaction->id(),
[&]() -> std::string {
std::stringstream ss;
int count = 0;
@@ -1040,7 +1040,7 @@ namespace gridfire {
LOG_TRACE_L3(
m_logger,
"Reaction {} is external to the group containing {} and contributes to external flux by {}",
reaction.id(),
reaction->id(),
[&]() -> std::string {
std::stringstream ss;
int count = 0;
@@ -1406,13 +1406,13 @@ namespace gridfire {
for (const auto& reactant : reaction->reactants()) {
if (std::ranges::find(pool, m_baseEngine.getSpeciesIndex(reactant)) == pool.end()) {
has_external_reactant = true;
LOG_TRACE_L3(m_logger, "Found external reactant {} in reaction {} for species {}.", reactant.name(), reaction.id(), ash.name());
LOG_TRACE_L3(m_logger, "Found external reactant {} in reaction {} for species {}.", reactant.name(), reaction->id(), ash.name());
break; // Found an external reactant, no need to check further
}
}
if (has_external_reactant) {
double flow = std::abs(m_baseEngine.calculateMolarReactionFlow(*reaction, Y, T9, rho));
LOG_TRACE_L3(m_logger, "Found bridge reaction {} with flow {} for species {}.", reaction.id(), flow, ash.name());
LOG_TRACE_L3(m_logger, "Found bridge reaction {} with flow {} for species {}.", reaction->id(), flow, ash.name());
bridge_reactions.emplace_back(reaction.get(), flow);
}
}