feat(Comoposition-Tracking): updated GridFire to use new, molar-abundance based, version of libcomposition (v2.0.6)

This entailed a major rewrite of the composition handling from each engine and engine view along with the solver and primer. The intent here is to let Compositions be constructed from the same extensive property which the solver tracks internally. This addressed C0 discontinuity issues in the tracked molar abundances of species which were introduced by repeadidly swaping from molar abundance space to mass fraction space and back. This also allowed for a simplification of the primeNetwork method. Specifically the mass borrowing system was dramatically simplified as molar abundances are extensive.
This commit is contained in:
2025-11-10 10:40:03 -05:00
parent 534a44448b
commit a7a4a30028
57 changed files with 1878 additions and 2823 deletions

View File

@@ -10,6 +10,8 @@
#include "gridfire/expectations/expected_engine.h"
#include "fourdst/composition/composition_abstract.h"
#include <vector>
#include <unordered_map>
#include <utility>
@@ -58,7 +60,7 @@ namespace gridfire {
*/
template <IsArithmeticOrAD T>
struct StepDerivatives {
std::map<fourdst::atomic::Species, T> dydt; ///< Derivatives of abundances (dY/dt for each species).
std::map<fourdst::atomic::Species, T> dydt{}; ///< Derivatives of abundances (dY/dt for each species).
T nuclearEnergyGenerationRate = T(0.0); ///< Specific energy generation rate (e.g., erg/g/s).
StepDerivatives() : dydt(), nuclearEnergyGenerationRate(T(0.0)) {}
@@ -120,7 +122,7 @@ namespace gridfire {
* rate for the current state.
*/
[[nodiscard]] virtual std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const = 0;
@@ -153,20 +155,20 @@ namespace gridfire {
* for the current state. The matrix can then be accessed via getJacobianMatrixEntry().
*/
virtual void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const = 0;
virtual void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species>& activeSpecies
) const = 0;
virtual void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const SparsityPattern& sparsityPattern
@@ -223,7 +225,7 @@ namespace gridfire {
*/
[[nodiscard]] virtual double calculateMolarReactionFlow(
const reaction::Reaction& reaction,
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const = 0;
@@ -240,7 +242,7 @@ namespace gridfire {
* generation rate with respect to temperature and density for the current state.
*/
[[nodiscard]] virtual EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const = 0;
@@ -266,13 +268,13 @@ namespace gridfire {
* which can be used for timestep control, diagnostics, and reaction network culling.
*/
[[nodiscard]] virtual std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const = 0;
[[nodiscard]] virtual std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const = 0;
@@ -390,7 +392,7 @@ namespace gridfire {
* which may involve adding or removing species and reactions based on the
* specified depth. However, not all engines support this operation.
*/
virtual void rebuild(const fourdst::composition::Composition& comp, BuildDepthType depth) {
virtual void rebuild(const fourdst::composition::CompositionAbstract &comp, BuildDepthType depth) {
throw std::logic_error("Setting network depth not supported by this engine.");
// ReSharper disable once CppDFAUnreachableCode
}
@@ -408,7 +410,7 @@ namespace gridfire {
* example, by either QSE partitioning or reaction flow rate culling
*/
virtual fourdst::composition::Composition collectComposition(
fourdst::composition::Composition& comp
fourdst::composition::CompositionAbstract &comp
) const = 0;
};

View File

@@ -1,331 +0,0 @@
/* ***********************************************************************
//
// Copyright (C) 2025 -- The 4D-STAR Collaboration
// File Author: Emily Boudreaux
// Last Modified: March 21, 2025
//
// 4DSSE is free software; you can use it and/or modify
// it under the terms and restrictions the GNU General Library Public
// License version 3 (GPLv3) as published by the Free Software Foundation.
//
// 4DSSE is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this software; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// *********************************************************************** */
#pragma once
#include <array>
#include <boost/numeric/odeint.hpp>
#include "gridfire/network.h"
/**
* @file approx8.h
* @brief Header file for the Approx8 nuclear reaction network.
*
* This file contains the definitions and declarations for the Approx8 nuclear reaction network.
* The network is based on Frank Timmes' "approx8" and includes 8 isotopes and various nuclear reactions.
* The rates are evaluated using a fitting function with coefficients from reaclib.jinaweb.org.
*/
namespace gridfire::approx8{
/**
* @typedef vector_type
* @brief Alias for a vector of doubles using Boost uBLAS.
*/
typedef boost::numeric::ublas::vector< double > vector_type;
/**
* @typedef matrix_type
* @brief Alias for a matrix of doubles using Boost uBLAS.
*/
typedef boost::numeric::ublas::matrix< double > matrix_type;
/**
* @typedef vec7
* @brief Alias for a std::array of 7 doubles.
*/
typedef std::array<double,7> vec7;
/**
* @struct Approx8Net
* @brief Contains constants and arrays related to the nuclear network.
*/
struct Approx8Net{
static constexpr int ih1=0;
static constexpr int ihe3=1;
static constexpr int ihe4=2;
static constexpr int ic12=3;
static constexpr int in14=4;
static constexpr int io16=5;
static constexpr int ine20=6;
static constexpr int img24=7;
static constexpr int iTemp=img24+1;
static constexpr int iDensity =iTemp+1;
static constexpr int iEnergy=iDensity+1;
static constexpr int nIso=img24+1; // number of isotopes
static constexpr int nVar=iEnergy+1; // number of variables
static constexpr std::array<int,nIso> aIon = {
1,
3,
4,
12,
14,
16,
20,
24
};
static constexpr std::array<double,nIso> mIon = {
1.67262164e-24,
5.00641157e-24,
6.64465545e-24,
1.99209977e-23,
2.32462686e-23,
2.65528858e-23,
3.31891077e-23,
3.98171594e-23
};
};
/**
* @brief Multiplies two arrays and sums the resulting elements.
* @param a First array.
* @param b Second array.
* @return Sum of the product of the arrays.
* @example
* @code
* vec7 a = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0};
* vec7 b = {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5};
* double result = sum_product(a, b);
* @endcode
*/
double sum_product( const vec7 &a, const vec7 &b);
/**
* @brief Returns an array of T9 terms for the nuclear reaction rate fit.
* @param T Temperature in GigaKelvin.
* @return Array of T9 terms.
* @example
* @code
* double T = 1.5;
* vec7 T9_array = get_T9_array(T);
* @endcode
*/
vec7 get_T9_array(const double &T);
/**
* @brief Evaluates the nuclear reaction rate given the T9 array and coefficients.
* @param T9 Array of T9 terms.
* @param coef Array of coefficients.
* @return Evaluated rate.
* @example
* @code
* vec7 T9 = get_T9_array(1.5);
* vec7 coef = {1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001};
* double rate = rate_fit(T9, coef);
* @endcode
*/
double rate_fit(const vec7 &T9, const vec7 &coef);
/**
* @brief Calculates the rate for the reaction p + p -> d.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double pp_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction p + d -> he3.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double dp_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction he3 + he3 -> he4 + 2p.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double he3he3_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction he3(he3,2p)he4.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double he3he4_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction he4 + he4 + he4 -> c12.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double triple_alpha_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction c12 + p -> n13.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double c12p_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction c12 + he4 -> o16.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double c12a_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction n14(p,g)o15 - o15 + p -> c12 + he4.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double n14p_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction n14(a,g)f18 assumed to go on to ne20.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double n14a_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction n15(p,a)c12 (CNO I).
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double n15pa_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction n15(p,g)o16 (CNO II).
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double n15pg_rate(const vec7 &T9);
/**
* @brief Calculates the fraction for the reaction n15(p,g)o16.
* @param T9 Array of T9 terms.
* @return Fraction of the reaction.
*/
double n15pg_frac(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction o16(p,g)f17 then f17 -> o17(p,a)n14.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double o16p_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction o16(a,g)ne20.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double o16a_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction ne20(a,g)mg24.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double ne20a_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction c12(c12,a)ne20.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double c12c12_rate(const vec7 &T9);
/**
* @brief Calculates the rate for the reaction c12(o16,a)mg24.
* @param T9 Array of T9 terms.
* @return Rate of the reaction.
*/
double c12o16_rate(const vec7 &T9);
/**
* @struct Jacobian
* @brief Functor to calculate the Jacobian matrix for implicit solvers.
*/
struct Jacobian {
/**
* @brief Calculates the Jacobian matrix.
* @param y State vector.
* @param J Jacobian matrix.
* @param dfdt Derivative of the state vector.
*/
void operator() ( const vector_type &y, matrix_type &J, double /* t */, vector_type &dfdt ) const;
};
/**
* @struct ODE
* @brief Functor to calculate the derivatives for the ODE solver.
*/
struct ODE {
/**
* @brief Calculates the derivatives of the state vector.
* @param y State vector.
* @param dydt Derivative of the state vector.
*/
void operator() ( const vector_type &y, vector_type &dydt, double /* t */) const;
};
/**
* @class Approx8Network
* @brief Class for the Approx8 nuclear reaction network.
*/
class Approx8Network final : public Network {
public:
Approx8Network();
/**
* @brief Evaluates the nuclear network.
* @param netIn Input parameters for the network.
* @return Output results from the network.
*/
NetOut evaluate(const NetIn &netIn) override;
/**
* @brief Sets whether the solver should use a stiff method.
* @param stiff Boolean indicating if a stiff method should be used.
*/
void setStiff(bool stiff) override;
/**
* @brief Checks if the solver is using a stiff method.
* @return Boolean indicating if a stiff method is being used.
*/
bool isStiff() const override { return m_stiff; }
private:
vector_type m_y;
double m_tMax = 0;
double m_dt0 = 0;
bool m_stiff = false;
/**
* @brief Converts the input parameters to the internal state vector.
* @param netIn Input parameters for the network.
* @return Internal state vector.
*/
static vector_type convert_netIn(const NetIn &netIn);
};
} // namespace nnApprox8

View File

@@ -1,6 +1,6 @@
#pragma once
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/composition/composition.h"
#include "fourdst/logging/logging.h"
#include "fourdst/config/config.h"
@@ -150,7 +150,7 @@ namespace gridfire {
* @see StepDerivatives
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -172,7 +172,7 @@ namespace gridfire {
* @see StepDerivatives
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract& comp,
double T9,
double rho,
const reaction::ReactionSet &activeReactions
@@ -193,7 +193,7 @@ namespace gridfire {
* @see EnergyDerivatives
*/
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -217,7 +217,7 @@ namespace gridfire {
* @see EnergyDerivatives
*/
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const reaction::ReactionSet &activeReactions
@@ -237,7 +237,7 @@ namespace gridfire {
* @see getJacobianMatrixEntry()
*/
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -255,7 +255,7 @@ namespace gridfire {
* @see generateJacobianMatrix()
*/
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species>& activeSpecies
@@ -277,7 +277,7 @@ namespace gridfire {
* @see getJacobianMatrixEntry()
*/
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const SparsityPattern &sparsityPattern
@@ -306,7 +306,7 @@ namespace gridfire {
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction& reaction,
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -388,7 +388,7 @@ namespace gridfire {
* which can be used for timestep control or diagnostics.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -407,7 +407,7 @@ namespace gridfire {
* calculations with different reaction sets without modifying the engine's internal state.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const reaction::ReactionSet &activeReactions
@@ -426,7 +426,7 @@ namespace gridfire {
* which can be useful for understanding reaction flows and equilibrium states.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -445,7 +445,7 @@ namespace gridfire {
* calculations with different reaction sets without modifying the engine's internal state.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const reaction::ReactionSet &activeReactions
@@ -606,7 +606,7 @@ namespace gridfire {
const reaction::Reaction &reaction,
double T9,
double rho,
const fourdst::composition::Composition& comp
const fourdst::composition::CompositionAbstract &comp
) const;
/**
@@ -733,7 +733,7 @@ namespace gridfire {
* and build depth. It updates all internal data structures accordingly.
*/
void rebuild(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
BuildDepthType depth
) override;
@@ -748,25 +748,25 @@ namespace gridfire {
* have a molar abundance set to 0.
* @throws BadCollectionError If the input composition contains species not present in the network species set
*/
fourdst::composition::Composition collectComposition(fourdst::composition::Composition &comp) const override;
fourdst::composition::Composition collectComposition(fourdst::composition::CompositionAbstract &comp) const override;
private:
struct PrecomputedReaction {
// Forward cacheing
size_t reaction_index;
reaction::ReactionType reaction_type;
uint64_t reaction_hash;
std::vector<size_t> unique_reactant_indices;
std::vector<int> reactant_powers;
double symmetry_factor;
std::vector<size_t> affected_species_indices;
std::vector<int> stoichiometric_coefficients;
size_t reaction_index{};
reaction::ReactionType reaction_type{};
uint64_t reaction_hash{};
std::vector<size_t> unique_reactant_indices{};
std::vector<int> reactant_powers{};
double symmetry_factor{};
std::vector<size_t> affected_species_indices{};
std::vector<int> stoichiometric_coefficients{};
// Reverse cacheing
std::vector<size_t> unique_product_indices; ///< Unique product indices for reverse reactions.
std::vector<int> product_powers; ///< Powers of each unique product in the reverse reaction.
double reverse_symmetry_factor; ///< Symmetry factor for reverse reactions.
std::vector<size_t> unique_product_indices{}; ///< Unique product indices for reverse reactions.
std::vector<int> product_powers{}; ///< Powers of each unique product in the reverse reaction.
double reverse_symmetry_factor{}; ///< Symmetry factor for reverse reactions.
};
struct constants {
@@ -955,7 +955,7 @@ namespace gridfire {
[[nodiscard]] StepDerivatives<double> calculateAllDerivativesUsingPrecomputation(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
const std::vector<double> &bare_rates,
const std::vector<double> &bare_reverse_rates,
double T9,

View File

@@ -3,7 +3,7 @@
#include "gridfire/reaction/reaction.h"
#include "gridfire/engine/types/building.h"
#include "fourdst/composition/composition.h"
#include "fourdst/composition/composition_abstract.h"
#include <variant>
@@ -113,7 +113,7 @@ namespace gridfire {
* @throws std::logic_error If the resolved network depth is zero (no reactions can be collected).
*/
reaction::ReactionSet build_nuclear_network(
const fourdst::composition::Composition &composition,
const fourdst::composition::CompositionAbstract &composition,
const rates::weak::WeakRateInterpolator &weakInterpolator,
BuildDepthType maxLayers = NetworkBuildDepth::Full,
NetworkConstructionFlags ReactionTypes = NetworkConstructionFlags::DEFAULT

View File

@@ -4,7 +4,7 @@
#include "gridfire/engine/engine_graph.h"
#include "gridfire/network.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
namespace gridfire {

View File

@@ -2,14 +2,12 @@
#include <map>
#include <string>
#include <ranges>
// Required for PrimingReport fields and streaming
#include <vector>
#include <utility>
#include <ostream>
#include <sstream>
#include "fourdst/composition/composition.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
namespace gridfire {

View File

@@ -5,7 +5,7 @@
#include "gridfire/screening/screening_types.h"
#include "gridfire/network.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/config/config.h"
#include "fourdst/logging/logging.h"
@@ -102,7 +102,7 @@ namespace gridfire {
* @see AdaptiveEngineView::update()
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -116,7 +116,7 @@ namespace gridfire {
* @return A struct containing the derivatives of the energy generation rate with respect to temperature and density.
*/
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -135,20 +135,20 @@ namespace gridfire {
* @see AdaptiveEngineView::update()
*/
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species> &activeSpecies
) const override;
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const SparsityPattern &sparsityPattern
@@ -220,7 +220,7 @@ namespace gridfire {
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction &reaction,
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -248,13 +248,13 @@ namespace gridfire {
* @throws std::runtime_error If the AdaptiveEngineView is stale (i.e., `update()` has not been called).
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -303,7 +303,7 @@ namespace gridfire {
[[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
fourdst::composition::Composition collectComposition(fourdst::composition::Composition &comp) const override;
fourdst::composition::Composition collectComposition(fourdst::composition::CompositionAbstract &comp) const override;
private:
using Config = fourdst::config::Config;
using LogManager = fourdst::logging::LogManager;

View File

@@ -43,13 +43,13 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale (i.e., `update()` has not been called after `setNetworkFile()`).
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -64,7 +64,7 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale.
*/
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -80,7 +80,7 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale.
*/
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species> &activeSpecies
@@ -97,7 +97,7 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale.
*/
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const SparsityPattern &sparsityPattern
@@ -150,7 +150,7 @@ namespace gridfire{
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction& reaction,
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -175,13 +175,13 @@ namespace gridfire{
* @throws std::runtime_error If the view is stale.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -221,7 +221,7 @@ namespace gridfire{
[[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
fourdst::composition::Composition collectComposition(fourdst::composition::Composition &comp) const override;
fourdst::composition::Composition collectComposition(fourdst::composition::CompositionAbstract &comp) const override;
protected:
bool m_isStale = true;
GraphEngine& m_baseEngine;

View File

@@ -231,13 +231,13 @@ namespace gridfire {
* (T9, rho, Y_full). This indicates `update()` was not called recently enough.
*/
[[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
[[nodiscard]] EnergyDerivatives calculateEpsDerivatives(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -266,7 +266,7 @@ namespace gridfire {
* without a valid partition.
*/
void generateJacobianMatrix(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -295,7 +295,7 @@ namespace gridfire {
* @throws exceptions::StaleEngineError If the QSE cache misses.
*/
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const std::vector<fourdst::atomic::Species> &activeSpecies
@@ -323,7 +323,7 @@ namespace gridfire {
* @throws exceptions::StaleEngineError If the QSE cache misses.
*/
void generateJacobianMatrix(
const fourdst::composition::Composition &comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho,
const SparsityPattern &sparsityPattern
@@ -407,7 +407,7 @@ namespace gridfire {
*/
[[nodiscard]] double calculateMolarReactionFlow(
const reaction::Reaction &reaction,
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -461,7 +461,7 @@ namespace gridfire {
* @throws StaleEngineError If the QSE cache misses.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -487,7 +487,7 @@ namespace gridfire {
* @throws StaleEngineError If the QSE cache misses.
*/
[[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
const fourdst::composition::Composition& comp,
const fourdst::composition::CompositionAbstract &comp,
double T9,
double rho
) const override;
@@ -792,7 +792,7 @@ namespace gridfire {
* @return New composition which is comp + any edits from lower levels + the equilibrium abundances of all algebraic species.
* @throws BadCollectionError: if there is a species in the algebraic species set which does not show up in the reported composition from the base engine.:w
*/
fourdst::composition::Composition collectComposition(fourdst::composition::Composition &comp) const override;
fourdst::composition::Composition collectComposition(fourdst::composition::CompositionAbstract &comp) const override;
private:

View File

@@ -3,7 +3,7 @@
#include "gridfire/engine/views/engine_defined.h"
#include "fourdst/logging/logging.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "quill/Logger.h"

View File

@@ -13,6 +13,7 @@
#include <exception>
#include <string>
#include <utility>
namespace gridfire::exceptions {
/**
@@ -28,7 +29,7 @@ namespace gridfire::exceptions {
* @brief Constructs a PolicyError with a descriptive message.
* @param msg The error message.
*/
explicit PolicyError(const std::string& msg) : m_message(msg) {};
explicit PolicyError(std::string msg) : m_message(std::move(msg)) {};
/**
* @brief Returns the explanatory string.

View File

@@ -5,14 +5,9 @@
#include <utility>
namespace gridfire::exceptions {
class UtilityError : public std::exception {};
class HashingError final : public UtilityError {
class UtilityError : public std::exception {
public:
explicit HashingError() = default;
explicit HashingError(std::string message)
: m_message(std::move(message)) {}
explicit UtilityError(std::string message) : m_message(std::move(message)) {}
[[nodiscard]] const char* what() const noexcept override {
return m_message.c_str();
@@ -20,4 +15,11 @@ namespace gridfire::exceptions {
private:
std::string m_message;
};
class HashingError final : public UtilityError {
public:
explicit HashingError(const std::string &message) : UtilityError(message) {}
};
}

View File

@@ -22,13 +22,7 @@
#include <vector>
#include "fourdst/logging/logging.h"
#include "fourdst/config/config.h"
#include "fourdst/composition/species.h"
#include "fourdst/composition/composition.h"
#include "fourdst/constants/const.h"
#include "quill/Logger.h"
#include <unordered_map>
@@ -56,8 +50,6 @@ namespace gridfire {
double density; ///< Density in g/cm^3
double energy; ///< Energy in ergs
double culling = 0.0; ///< Culling threshold for reactions (default is 0.0, meaning no culling)
[[nodiscard]] std::vector<double> MolarAbundance() const;
};
struct NetOut {
@@ -73,36 +65,4 @@ namespace gridfire {
}
};
class Network {
public:
explicit Network(const NetworkFormat format = NetworkFormat::APPROX8);
virtual ~Network() = default;
[[nodiscard]] NetworkFormat getFormat() const;
NetworkFormat setFormat(const NetworkFormat format);
/**
* @brief Evaluate the network based on the input parameters.
*
* @param netIn Input parameters for the network evaluation.
* @return NetOut Output results from the network evaluation.
*/
virtual NetOut evaluate(const NetIn &netIn) = 0;
[[nodiscard]] virtual bool isStiff() const { return m_stiff; }
virtual void setStiff(const bool stiff) { m_stiff = stiff; }
protected:
fourdst::config::Config& m_config; ///< Configuration instance
fourdst::logging::LogManager& m_logManager; ///< Log manager instance
quill::Logger* m_logger; ///< Logger instance
NetworkFormat m_format; ///< Format of the network
fourdst::constant::Constants& m_constants;
bool m_stiff = false; ///< Flag indicating if the network is stiff
};
} // namespace nuclearNetwork

View File

@@ -21,7 +21,7 @@
#pragma once
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "gridfire/reaction/reaction.h"
#include "gridfire/engine/engine_abstract.h"

View File

@@ -45,7 +45,7 @@ namespace gridfire::policy {
auto end() { return m_chain_policies.end(); }
[[nodiscard]] auto end() const { return m_chain_policies.cend(); }
protected:
std::vector<std::unique_ptr<ReactionChainPolicy>> m_chain_policies;
std::vector<std::unique_ptr<ReactionChainPolicy>> m_chain_policies{};
reaction::ReactionSet m_reactions;
};
}

View File

@@ -25,7 +25,7 @@
#include "fourdst/composition/composition.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "gridfire/partition/composite/partition_composite.h"
#include "gridfire/policy/chains.h"
@@ -91,7 +91,7 @@ namespace gridfire::policy {
* LowMassMainSequencePolicy policy(species, mass_fractions);
* @endcode
*/
explicit MainSequencePolicy(std::vector<fourdst::atomic::Species> seed_species, std::vector<double> mass_fractions);
explicit MainSequencePolicy(std::vector<fourdst::atomic::Species> seed_species, const std::vector<double> &mass_fractions);
/**
* @brief Returns the name of the policy.
@@ -143,16 +143,7 @@ namespace gridfire::policy {
*/
[[nodiscard]] NetworkPolicyStatus getStatus() const override;
private:
std::set<fourdst::atomic::Species> m_seed_species = {
fourdst::atomic::H_1,
fourdst::atomic::He_3,
fourdst::atomic::He_4,
fourdst::atomic::C_12,
fourdst::atomic::N_14,
fourdst::atomic::O_16,
fourdst::atomic::Ne_20,
fourdst::atomic::Mg_24
};
std::set<fourdst::atomic::Species> m_seed_species;
std::unique_ptr<ReactionChainPolicy> m_reaction_policy = std::make_unique<MainSequenceReactionChainPolicy>();
fourdst::composition::Composition m_initializing_composition;
@@ -162,7 +153,7 @@ namespace gridfire::policy {
NetworkPolicyStatus m_status = NetworkPolicyStatus::UNINITIALIZED;
private:
static std::unique_ptr<partition::PartitionFunction> build_partition_function();
NetworkPolicyStatus check_status() const;
[[nodiscard]] NetworkPolicyStatus check_status() const;
};

View File

@@ -3,7 +3,7 @@
#include <ranges>
#include <string_view>
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/logging/logging.h"
#include "quill/Logger.h"
#include <unordered_map>

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
#include "gridfire/engine/engine_abstract.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/constants/const.h"
#include "cppad/cppad.hpp"

View File

@@ -1,7 +1,7 @@
#pragma once
#include "gridfire/reaction/weak/weak_types.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/logging/logging.h"
#include <unordered_map>

View File

@@ -2,7 +2,7 @@
#include "gridfire/reaction/reaction.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "cppad/cppad.hpp"

View File

@@ -14,7 +14,7 @@ namespace gridfire::solver {
* @struct SolverContextBase
* @brief Base class for solver callback contexts.
*
* This struct serves as a base class for contexts that can be papubl;ssed to solver callbacks, it enforces
* This struct serves as a base class for contexts that can be passed to solver callbacks, it enforces
* that derived classes implement a `describe` method that returns a vector of tuples describing
* the context that a callback will receive when called.
*/

View File

@@ -5,7 +5,7 @@
#include "gridfire/network.h"
#include "gridfire/exceptions/exceptions.h"
#include "fourdst/composition/atomicSpecies.h"
#include "fourdst/atomic/atomicSpecies.h"
#include "fourdst/config/config.h"
@@ -176,7 +176,7 @@ namespace gridfire::solver {
const DynamicEngine& engine; ///< Reference to the engine.
const std::vector<fourdst::atomic::Species>& networkSpecies; ///< Species layout.
const size_t currentConvergenceFailures; ///< Total number of convergence failures
const size_t currentNonlinearIterations; ///< Total number of non linear iterations
const size_t currentNonlinearIterations; ///< Total number of non-linear iterations
/**
* @brief Construct a context snapshot.
@@ -216,12 +216,12 @@ namespace gridfire::solver {
* to CVODE, then the driver loop inspects and rethrows.
*/
struct CVODEUserData {
CVODESolverStrategy* solver_instance; // Pointer back to the class instance
DynamicEngine* engine;
double T9;
double rho;
double energy;
const std::vector<fourdst::atomic::Species>* networkSpecies;
CVODESolverStrategy* solver_instance{}; // Pointer back to the class instance
DynamicEngine* engine{};
double T9{};
double rho{};
double energy{};
const std::vector<fourdst::atomic::Species>* networkSpecies{};
std::unique_ptr<exceptions::StaleEngineTrigger> captured_exception = nullptr;
};

View File

@@ -1,81 +0,0 @@
#pragma once
#include "fourdst/composition/composition.h"
#include "fourdst/composition/atomicSpecies.h"
#include <ranges>
namespace gridfire::utils {
inline double massFractionFromMolarAbundanceAndComposition (
const fourdst::composition::Composition& composition,
const fourdst::atomic::Species& species,
const double Yi
) {
double sum = 0;
for (const auto& [symbol, entry] : composition) {
if (entry.isotope() == species) {
sum += species.mass() * Yi;
} else {
sum += entry.isotope().mass() * composition.getMolarAbundance(symbol);
}
}
return (species.mass() * Yi) / sum;
};
/**
* @brief Convert a vector of molar abundances into a vector of mass fractions
* @param molarAbundances Vector of molar abundances
* @param molarMasses Vector of molar masses
*
* @note The vectors molarAbundances and molarMasses must be parallel. This function does not provide any checks
* to ensure that the correct molar mass is being used with the correct molar abundance.
* @return A vector of molar masses such that each molar mass < 1 and the sum of all is = 1
*/
inline std::vector<double> massFractionFromMolarAbundanceAndMolarMass (
const std::vector<double>& molarAbundances,
const std::vector<double>& molarMasses
) noexcept {
assert(molarMasses.size() == molarAbundances.size());
assert(!molarMasses.empty());
double totalMass = 0;
std::vector<double> masses;
masses.reserve(molarMasses.size());
for (const auto [m, Y] : std::views::zip(molarMasses, molarAbundances)) {
const double mass = m * Y;
totalMass += mass;
masses.push_back(mass);
}
assert(totalMass > 0);
std::vector<double> massFractions;
massFractions.reserve(masses.size());
std::ranges::transform(
masses,
std::back_inserter(massFractions),
[&totalMass](const double speciesMass) {
const double Xi = speciesMass / totalMass;
if (std::abs(Xi) < 1e-16 && Xi < 0) {
return 0.0;
}
return Xi;
});
return massFractions;
}
inline std::vector<double> molarMassVectorFromComposition(
const fourdst::composition::Composition& composition
) {
std::map<fourdst::atomic::Species, double> molarMassMap;
for (const auto &entry: composition | std::views::values) {
molarMassMap.emplace(entry.isotope(), entry.isotope().mass());
}
std::vector<double> molarMassVector;
molarMassVector.reserve(molarMassMap.size());
for (const auto molarMass : molarMassMap | std::views::values) {
molarMassVector.push_back(molarMass);
}
return molarMassVector;
}
}

View File

@@ -9,9 +9,50 @@
#include <algorithm>
#include <numeric>
#include <memory>
#include <format>
#include <print>
#include <cstdlib>
#include <cwchar>
#include <clocale>
namespace gridfire::utils {
inline size_t visual_width(const std::string& s) {
// IMPORTANT: std::setlocale(LC_ALL, "") must be called once in main()
// for mbtowc and wcwidth to function correctly with the system's locale.
size_t width = 0;
std::mbtowc(nullptr, 0, 0); // Reset multi-byte state
const char* p = s.c_str();
const char* end = s.c_str() + s.length();
while (p < end) {
wchar_t wc;
// Convert the next multi-byte char to a wide char
int byte_len = std::mbtowc(&wc, p, end - p);
if (byte_len <= 0) {
// Invalid byte sequence or null char.
// Treat as a 1-width '?' and advance by 1 byte to avoid infinite loop.
width++;
p++;
continue;
}
// Get the visual width of the wide char
int char_width = wcwidth(wc);
if (char_width != -1) {
width += char_width;
}
// else: char_width == -1 means non-printable/control char; treat as 0 width
p += byte_len; // Advance by the number of bytes consumed
}
return width;
}
class ColumnBase {
public:
virtual ~ColumnBase() = default;
@@ -117,6 +158,87 @@ namespace gridfire::utils {
return table_ss.str();
}
inline void print_table(const std::string& tableName, const std::vector<std::unique_ptr<ColumnBase>>& columns) {
// --- 1. Handle Empty Table ---
if (columns.empty()) {
std::println("{} \n(Table has no columns)\n", tableName);
return;
}
// --- 2. Determine dimensions and calculate column widths (using visual_width) ---
size_t num_cols = columns.size();
size_t num_rows = 0;
for (const auto& col : columns) {
num_rows = std::max(num_rows, col->getRowCount());
}
std::vector<size_t> col_widths(num_cols);
for (size_t j = 0; j < num_cols; ++j) {
// Start with header width
col_widths[j] = visual_width(columns[j]->getHeader());
// Find max width in all data cells
for (size_t i = 0; i < num_rows; ++i) {
col_widths[j] = std::max(col_widths[j], visual_width(columns[j]->getCellData(i)));
}
}
// --- 3. Print the table using std::print / std::println ---
// --- Table Title ---
// NOLINTNEXTLINE(*-fold-init-type)
const size_t total_width = std::accumulate(col_widths.begin(), col_widths.end(), 0UL) + (num_cols * 3) + 1;
const size_t title_padding_len = (total_width > visual_width(tableName)) ? (total_width - visual_width(tableName)) / 2 : 0;
// Print padding, then title
std::print("{: <{}}", "", title_padding_len); // Left-aligned empty string "" of width title_padding_len
std::println("{}", tableName);
// --- Helper to draw horizontal border ---
auto draw_border = [&]() {
std::print("+");
for (const size_t width : col_widths) {
// std::string(width + 2, '-') is still the easiest way to repeat a char
std::print("{:-<{}}+", "", width + 2); // Prints '-' repeated (width + 2) times
}
std::println("");
};
// --- Draw Top Border ---
draw_border();
// --- Helper to print a cell with correct padding ---
auto print_cell = [&](const std::string& text, size_t width) {
size_t text_width = visual_width(text);
size_t padding = (width >= text_width) ? (width - text_width) : 0;
// Print text and then the manual padding
std::print(" {}{: <{}} |", text, "", padding);
};
// --- Draw Header Row ---
std::print("|");
for (size_t j = 0; j < num_cols; ++j) {
print_cell(columns[j]->getHeader(), col_widths[j]);
}
std::println("");
// --- Draw Separator ---
draw_border();
// --- Draw Data Rows ---
for (size_t i = 0; i < num_rows; ++i) {
std::print("|");
for (size_t j = 0; j < num_cols; ++j) {
print_cell(columns[j]->getCellData(i), col_widths[j]);
}
std::println("");
}
// --- Draw Bottom Border ---
draw_border();
}
}