perf(thread saftey): All Engines are now thread safe

Previously engines were not thread safe, a seperate engine would be
needed for every thread. This is no longer the case. This allows for
much more efficient parallel execution
This commit is contained in:
2025-12-12 12:08:47 -05:00
parent c7574a2f3d
commit e114c0e240
46 changed files with 3685 additions and 1604 deletions

View File

@@ -78,14 +78,17 @@ namespace gridfire::solver {
* std::cout << "Final energy: " << out.energy << " erg/g\n";
* @endcode
*/
class CVODESolverStrategy final : public SingleZoneDynamicNetworkSolverStrategy {
class CVODESolverStrategy final : public SingleZoneDynamicNetworkSolver {
public:
/**
* @brief Construct the CVODE strategy and create a SUNDIALS context.
* @param engine DynamicEngine used for RHS/Jacobian evaluation and network access.
* @throws std::runtime_error If SUNContext_Create fails.
*/
explicit CVODESolverStrategy(engine::DynamicEngine& engine);
explicit CVODESolverStrategy(
const engine::DynamicEngine& engine,
const engine::scratch::StateBlob& ctx
);
/**
* @brief Destructor: cleans CVODE/SUNDIALS resources and frees SUNContext.
*/
@@ -185,6 +188,7 @@ namespace gridfire::solver {
const size_t currentConvergenceFailures; ///< Total number of convergence failures
const size_t currentNonlinearIterations; ///< Total number of non-linear iterations
const std::map<fourdst::atomic::Species, std::unordered_map<std::string, double>>& reactionContributionMap; ///< Map of reaction contributions for the current step
engine::scratch::StateBlob& state_ctx; ///< Reference to the engine scratch state blob
/**
* @brief Construct a context snapshot.
@@ -201,7 +205,8 @@ namespace gridfire::solver {
const std::vector<fourdst::atomic::Species>& networkSpecies,
size_t currentConvergenceFailure,
size_t currentNonlinearIterations,
const std::map<fourdst::atomic::Species, std::unordered_map<std::string, double>> &reactionContributionMap
const std::map<fourdst::atomic::Species, std::unordered_map<std::string, double>> &reactionContributionMap,
engine::scratch::StateBlob& state_ctx
);
/**
@@ -226,7 +231,8 @@ namespace gridfire::solver {
*/
struct CVODEUserData {
CVODESolverStrategy* solver_instance{}; // Pointer back to the class instance
engine::DynamicEngine* engine{};
engine::scratch::StateBlob& ctx;
const engine::DynamicEngine* engine{};
double T9{};
double rho{};
double energy{};
@@ -302,7 +308,7 @@ namespace gridfire::solver {
* sorted table of species with the highest error ratios; then invokes diagnostic routines to
* inspect Jacobian stiffness and species balance.
*/
void log_step_diagnostics(const CVODEUserData& user_data, bool displayJacobianStiffness, bool
void log_step_diagnostics(engine::scratch::StateBlob &ctx, const CVODEUserData& user_data, bool displayJacobianStiffness, bool
displaySpeciesBalance, bool to_file, std::optional<std::string> filename) const;
private:
SUNContext m_sun_ctx = nullptr; ///< SUNDIALS context (lifetime of the solver).

View File

@@ -37,7 +37,7 @@ namespace gridfire::solver {
[[nodiscard]] virtual std::vector<std::tuple<std::string, std::string>> describe() const = 0;
};
/**
* @class SingleZoneNetworkSolverStrategy
* @class SingleZoneNetworkSolver
* @brief Abstract base class for network solver strategies.
*
* This class defines the interface for network solver strategies, which are responsible
@@ -47,18 +47,23 @@ namespace gridfire::solver {
* @tparam EngineT The type of engine to use with this solver strategy. Must inherit from Engine.
*/
template <IsEngine EngineT>
class SingleZoneNetworkSolverStrategy {
class SingleZoneNetworkSolver {
public:
/**
* @brief Constructor for the NetworkSolverStrategy.
* @param engine The engine to use for evaluating the network.
*/
explicit SingleZoneNetworkSolverStrategy(EngineT& engine) : m_engine(engine) {};
explicit SingleZoneNetworkSolver(
const EngineT& engine,
const engine::scratch::StateBlob& ctx
) :
m_engine(engine),
m_scratch_blob(ctx.clone_structure()) {};
/**
* @brief Virtual destructor.
*/
virtual ~SingleZoneNetworkSolverStrategy() = default;
virtual ~SingleZoneNetworkSolver() = default;
/**
* @brief Evaluates the network for a given timestep.
@@ -92,14 +97,21 @@ namespace gridfire::solver {
*/
[[nodiscard]] virtual std::vector<std::tuple<std::string, std::string>> describe_callback_context() const = 0;
protected:
EngineT& m_engine; ///< The engine used by this solver strategy.
const EngineT& m_engine; ///< The engine used by this solver strategy.
std::unique_ptr<engine::scratch::StateBlob> m_scratch_blob;
};
template <IsEngine EngineT>
class MultiZoneNetworkSolverStrategy {
class MultiZoneNetworkSolver {
public:
explicit MultiZoneNetworkSolverStrategy(EngineT& engine) : m_engine(engine) {};
virtual ~MultiZoneNetworkSolverStrategy() = default;
explicit MultiZoneNetworkSolver(
const EngineT& engine,
const engine::scratch::StateBlob& ctx
) :
m_engine(engine),
m_scratch_blob_structure(ctx.clone_structure()){};
virtual ~MultiZoneNetworkSolver() = default;
virtual std::vector<NetOut> evaluate(
const std::vector<NetIn>& netIns,
@@ -108,12 +120,13 @@ namespace gridfire::solver {
virtual void set_callback(const std::any& callback) = 0;
[[nodiscard]] virtual std::vector<std::tuple<std::string, std::string>> describe_callback_context() const = 0;
protected:
EngineT& m_engine; ///< The engine used by this solver strategy.
const EngineT& m_engine; ///< The engine used by this solver strategy.
std::unique_ptr<engine::scratch::StateBlob> m_scratch_blob_structure;
};
/**
* @brief Type alias for a network solver strategy that uses a DynamicEngine.
*/
using SingleZoneDynamicNetworkSolverStrategy = SingleZoneNetworkSolverStrategy<engine::DynamicEngine>;
using MultiZoneDynamicNetworkSolverStrategy = MultiZoneNetworkSolverStrategy<engine::DynamicEngine>;
using SingleZoneDynamicNetworkSolver = SingleZoneNetworkSolver<engine::DynamicEngine>;
using MultiZoneDynamicNetworkSolver = MultiZoneNetworkSolver<engine::DynamicEngine>;
}