From 534a44448b906df988dbe54e46b0f20cc446b305 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Thu, 6 Nov 2025 09:18:23 -0500 Subject: [PATCH] feat(policy): updateed policy system and added new reaction chains Reacions chains now contain more information and are broken out in a more detailed fashion. --- src/include/gridfire/policy/chains.h | 367 +++++++----------- src/include/gridfire/policy/policy_abstract.h | 52 ++- src/include/gridfire/policy/policy_logical.h | 51 +++ src/include/gridfire/policy/stellar_policy.h | 112 +----- src/include/gridfire/reaction/reaction.h | 3 +- src/include/gridfire/utils/hashing.h | 7 + src/lib/policy/chains.cpp | 337 ++++++++++++++++ src/lib/policy/policy_logical.cpp | 69 ++++ src/lib/policy/stellar_policy.cpp | 101 +++++ src/meson.build | 3 + 10 files changed, 732 insertions(+), 370 deletions(-) diff --git a/src/include/gridfire/policy/chains.h b/src/include/gridfire/policy/chains.h index d6c09f7d..0774ca64 100644 --- a/src/include/gridfire/policy/chains.h +++ b/src/include/gridfire/policy/chains.h @@ -6,7 +6,7 @@ * Proton-Proton chain and the CNO cycle. These policies inherit from ReactionChainPolicy (see * `policy_abstract.h`) and provide a pre-defined set of reactions. * - * They are typically used by higher-level NetworkPolicy implementations (e.g., `LowMassMainSequencePolicy` + * They are typically used by higher-level NetworkPolicy implementations (e.g., `MainSequencePolicy` * in `stellar_policy.h`) to compose a complete set of required reactions for a particular * stellar environment. * @@ -17,258 +17,153 @@ #pragma once #include "gridfire/policy/policy_abstract.h" +#include "gridfire/policy/policy_logical.h" #include "gridfire/reaction/reaction.h" -#include "gridfire/reaction/reaclib.h" - -#include "gridfire/exceptions/error_policy.h" - #include namespace gridfire::policy { - /** - * @class ProtonProtonChainPolicy - * @brief A ReactionChainPolicy for the Proton-Proton (PP) chain. - * - * Encapsulates the set of reactions that constitute the three branches of the PP chain, - * which is the primary energy generation mechanism in stars like the Sun. - * - * @throws gridfire::exceptions::MissingBaseReactionError if a required reaction for the PP chain - * is not found in the REACLIB database during construction. - */ - class ProtonProtonChainPolicy final: public ReactionChainPolicy { + class TemperatureDependentChainPolicy : public ReactionChainPolicy { + public: + explicit TemperatureDependentChainPolicy(const std::vector& reactionIDs); + explicit TemperatureDependentChainPolicy(const std::vector& reactionIDs, std::optional minT9); + explicit TemperatureDependentChainPolicy(const std::vector& reactionIDs, std::optional minT9, std::optional maxT9); + [[nodiscard]] const reaction::ReactionSet& get_reactions() const override; + [[nodiscard]] bool contains(const std::string& id) const override; + [[nodiscard]] bool contains(const reaction::Reaction& reaction) const override; + [[nodiscard]] uint64_t hash(uint64_t seed) const override; + [[nodiscard]] bool operator==(const ReactionChainPolicy& other) const override; + [[nodiscard]] bool operator!=(const ReactionChainPolicy& other) const override; + + [[nodiscard]] bool is_active(double T9) const; + + protected: + struct ActiveTempRange { + std::optional minT9; + std::optional maxT9; + }; + + ActiveTempRange m_tempRange; + std::vector m_reactionIDs; + reaction::ReactionSet m_reactions; + }; + + class ProtonProtonIChainPolicy final: public TemperatureDependentChainPolicy { + public: + ProtonProtonIChainPolicy(); + + [[nodiscard]] std::unique_ptr clone() const override; + + [[nodiscard]] std::string name() const override; + }; + + class ProtonProtonIIChainPolicy final: public TemperatureDependentChainPolicy { + public: + ProtonProtonIIChainPolicy(); + + [[nodiscard]] std::unique_ptr clone() const override; + + [[nodiscard]] std::string name() const override; + }; + + class ProtonProtonIIIChainPolicy final: public TemperatureDependentChainPolicy { + public: + ProtonProtonIIIChainPolicy(); + + [[nodiscard]] std::unique_ptr clone() const override; + + [[nodiscard]] std::string name() const override; + }; + + class ProtonProtonChainPolicy final : public MultiReactionChainPolicy { public: - /** - * @brief Constructs the policy and initializes its reaction set from REACLIB. - */ ProtonProtonChainPolicy(); - - /** - * @brief Returns the set of reactions in the PP chain. - * @return const reaction::ReactionSet& - * - * @par Example - * @code - * ProtonProtonChainPolicy pp_policy; - * const auto& reactions = pp_policy.get_reactions(); - * std::cout << "PP chain has " << reactions.size() << " reactions." << std::endl; - * @endcode - */ - [[nodiscard]] const reaction::ReactionSet& get_reactions() const override { return m_reactions; } - private: - std::vector m_reactionIDs = { - "p(p,e+)d", - "d(p,g)he3", - "he3(he3,2p)he4", - "he4(he3,g)be7", - "be7(e-,)li7", - "li7(p,a)he4", - "be7(p,g)b8", - "b8(,e+)be8", - "be8(,a)he4" - }; - reaction::ReactionSet m_reactions; - }; - - /** - * @class CNOChainPolicy - * @brief A ReactionChainPolicy for the Carbon-Nitrogen-Oxygen (CNO) cycle. - * - * Encapsulates the reactions of the CNO cycle, a catalytic cycle that is the dominant - * source of energy in massive stars. - * - * @throws gridfire::exceptions::MissingBaseReactionError if a required reaction for the CNO cycle - * is not found in the REACLIB database during construction. - */ - class CNOChainPolicy final: public ReactionChainPolicy { - public: - /** - * @brief Constructs the policy and initializes its reaction set from REACLIB. - */ - CNOChainPolicy(); - /** - * @brief Returns the set of reactions in the CNO cycle. - * @return const reaction::ReactionSet& - * - * @par Example - * @code - * CNOChainPolicy cno_policy; - * const auto& reactions = cno_policy.get_reactions(); - * assert(reactions.contains("c12(p,g)n13")); - * @endcode - */ - [[nodiscard]] const reaction::ReactionSet& get_reactions() const override { return m_reactions; } - private: - std::set m_reactionIDs = { - "c12(p,g)n13", - "n13(,e+)c13", - "c13(p,g)n14", - "n14(p,g)o15", - "o15(,e+)n15", - "n15(p,a)c12", - - "n15(p,g)o16", - "o16(p,g)f17", - "f17(,e+)o17", - "o17(p,a)n14", - "n14(p,g)o15", - "o15(,e+)n15", - - "o17(p,g)f18", - "f18(,e+)o18", - "o18(p,a)n15", - "n15(p,g)o16", - "o16(p,g)f17", - "f17(,e+)o17", - - "o18(p,g)f19", - "f19(p,a)o16", - "o16(p,g)f17", - "f17(,e+)o17", - "o17(p,g)f18", - "f18(,e+)o18" - }; - reaction::ReactionSet m_reactions; - }; - - /** - * @class HotCNOChainPolicy - * @brief A ReactionChainPolicy for the Hot CNO (HCNO) cycle. - * - * Encapsulates the reactions of the HCNO cycle, which becomes significant at higher - * temperatures and densities than the standard CNO cycle, often in explosive scenarios. - * - * @throws gridfire::exceptions::MissingBaseReactionError if a required reaction for the HCNO cycle - * is not found in the REACLIB database during construction. - */ - class HotCNOChainPolicy final : public ReactionChainPolicy { - public: - /** - * @brief Constructs the policy and initializes its reaction set from REACLIB. - */ - HotCNOChainPolicy(); - /** - * @brief Returns the set of reactions in the HCNO cycle. - * @return const reaction::ReactionSet& - */ - [[nodiscard]] const reaction::ReactionSet& get_reactions() const override { return m_reactions; } - private: - std::set m_reactionIDs = { - "c12(p,g)n13", - "n13(p,g)o14", - "o14(,e+)n14", - "n14(p,g)o15", - "o15(,e+)n15", - "n15(p,a)c12", - - "n15(p,g)o16", - "o16(p,g)f17", - "f17(p,g)ne18", - "ne18(,e+)f18", - "f18(p,a)o15", - "o15(,e+)n15", - - "f18(p,g)ne19", - "ne19(,e+)f19", - "f19(p,a)o16", - "o16(p,g)f17", - "f17(p,g)ne18", - "ne18(,e+)f18" - }; - - reaction::ReactionSet m_reactions; - }; - - /** - * @class LowMassMainSequenceReactionChainPolicy - * @brief A MultiReactionChainPolicy for low-mass main-sequence stars. - * - * This policy composes the `ProtonProtonChainPolicy` and `CNOChainPolicy` to represent the - * key energy-generating reaction chains active in low-mass stars like the Sun. - */ - class LowMassMainSequenceReactionChainPolicy final : public MultiReactionChainPolicy { - public: - /** - * @brief Constructs the policy and initializes its child policies. - */ - LowMassMainSequenceReactionChainPolicy(); - - /** - * @brief Returns the combined set of reactions from all child policies (PP and CNO). - * @return const reaction::ReactionSet& - */ - [[nodiscard]] const reaction::ReactionSet & get_reactions() const override; - - /** - * @brief Returns the vector of child policies. - * @return const std::vector>& - * - * @par Example - * @code - * LowMassMainSequenceReactionChainPolicy lmms_policy; - * const auto& child_policies = lmms_policy.get_chain_policies(); - * std::cout << "Low-mass policy has " << child_policies.size() << " child policies." << std::endl; - * @endcode - */ - [[nodiscard]] const std::vector>& get_chain_policies() const override; - + [[nodiscard]] std::string name() const override; private: std::vector> m_chain_policies; - reaction::ReactionSet m_reactions; }; - inline ProtonProtonChainPolicy::ProtonProtonChainPolicy() { - const auto& all_reaclib_reactions = reaclib::get_all_reaclib_reactions(); + class CNOIChainPolicy final : public TemperatureDependentChainPolicy { + public: + CNOIChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; - for (const auto& reactionID : m_reactionIDs) { - auto reaction = all_reaclib_reactions.get(reactionID); - if (!reaction) { - throw exceptions::MissingBaseReactionError("The Underlying REACLIB reaction set is missing the reaction " + std::string(reactionID) + " needed for the proton-proton chain. This indicates that there is an issue with the GridFire binary you are using. Please try to recompile and if that fails please report this issue to the developers."); - } - m_reactions.add_reaction(reaction.value()->clone()); - } - } + [[nodiscard]] std::string name() const override; + }; - inline CNOChainPolicy::CNOChainPolicy() { - const auto& all_reaclib_reactions = reaclib::get_all_reaclib_reactions(); - for (const auto& reactionID : m_reactionIDs) { - auto reaction = all_reaclib_reactions.get(reactionID); - if (!reaction) { - throw exceptions::MissingBaseReactionError("The Underlying REACLIB reaction set is missing the reaction " + std::string(reactionID) + " needed for the CNO cycle. This indicates that there is an issue with the GridFire binary you are using. Please try to recompile and if that fails please report this issue to the developers."); - } - m_reactions.add_reaction(reaction.value()->clone()); - } - } + class CNOIIChainPolicy final : public TemperatureDependentChainPolicy { + public: + CNOIIChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; - inline HotCNOChainPolicy::HotCNOChainPolicy() { - const auto& all_reaclib_reactions = reaclib::get_all_reaclib_reactions(); - for (const auto& reactionID : m_reactionIDs) { - auto reaction = all_reaclib_reactions.get(reactionID); - if (!reaction) { - throw exceptions::MissingBaseReactionError("The Underlying REACLIB reaction set is missing the reaction " + std::string(reactionID) + " needed for the Hot CNO cycle. This indicates that there is an issue with the GridFire binary you are using. Please try to recompile and if that fails please report this issue to the developers."); - } - m_reactions.add_reaction(reaction.value()->clone()); - } - } + [[nodiscard]] std::string name() const override; + }; + + class CNOIIIChainPolicy final : public TemperatureDependentChainPolicy { + public: + CNOIIIChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; + + [[nodiscard]] std::string name() const override; + }; + + class CNOIVChainPolicy final : public TemperatureDependentChainPolicy { + public: + CNOIVChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; + + [[nodiscard]] std::string name() const override; + }; + + class CNOChainPolicy final : public MultiReactionChainPolicy { + public: + CNOChainPolicy(); + [[nodiscard]] std::string name() const override; + }; + + class HotCNOIChainPolicy final : public TemperatureDependentChainPolicy { + public: + HotCNOIChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; + [[nodiscard]] std::string name() const override; + }; + + class HotCNOIIChainPolicy final : public TemperatureDependentChainPolicy { + public: + HotCNOIIChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; + [[nodiscard]] std::string name() const override; + }; + + class HotCNOIIIChainPolicy final : public TemperatureDependentChainPolicy { + public: + HotCNOIIIChainPolicy(); + [[nodiscard]] std::unique_ptr clone() const override; + [[nodiscard]] std::string name() const override; + }; + + class HotCNOChainPolicy final : public MultiReactionChainPolicy { + public: + HotCNOChainPolicy(); + [[nodiscard]] std::string name() const override; + }; + + class TripleAlphaChainPolicy final : public TemperatureDependentChainPolicy { + public: + TripleAlphaChainPolicy(); + + [[nodiscard]] std::unique_ptr clone() const override; + + [[nodiscard]] std::string name() const override; + }; - inline LowMassMainSequenceReactionChainPolicy::LowMassMainSequenceReactionChainPolicy() { - m_chain_policies.emplace_back(std::make_unique()); - m_chain_policies.emplace_back(std::make_unique()); - for (const auto& policy_ptr : m_chain_policies) { - m_reactions.extend(policy_ptr->get_reactions()); - } - } - - inline const reaction::ReactionSet & LowMassMainSequenceReactionChainPolicy::get_reactions() const { - return m_reactions; - } - - inline const std::vector>& LowMassMainSequenceReactionChainPolicy::get_chain_policies() const { - return m_chain_policies; - } - + class MainSequenceReactionChainPolicy final : public MultiReactionChainPolicy { + public: + MainSequenceReactionChainPolicy(); + [[nodiscard]] std::string name() const override; + }; } diff --git a/src/include/gridfire/policy/policy_abstract.h b/src/include/gridfire/policy/policy_abstract.h index 9c4865e1..dfacb7f8 100644 --- a/src/include/gridfire/policy/policy_abstract.h +++ b/src/include/gridfire/policy/policy_abstract.h @@ -22,7 +22,6 @@ #pragma once #include "fourdst/composition/atomicSpecies.h" -#include "gridfire/engine/types/building.h" #include "gridfire/reaction/reaction.h" #include "gridfire/engine/engine_abstract.h" @@ -57,7 +56,7 @@ namespace gridfire::policy { * - A constructor method that returns a fully constructed DynamicEngine (or view stack) built * to satisfy the policy. * - * Concrete implementations include `LowMassMainSequencePolicy` (see `stellar_policy.h`) and may + * Concrete implementations include `MainSequencePolicy` (see `stellar_policy.h`) and may * throw policy-specific exceptions during construction (for example when required reactions or * species are missing). * @@ -78,7 +77,7 @@ namespace gridfire::policy { /** * @brief Human-readable name for the policy. * - * @return a std::string identifying the policy implementation (e.g. "LowMassMainSequencePolicy"). + * @return a std::string identifying the policy implementation (e.g. "MainSequencePolicy"). * * @par Example * @code @@ -103,7 +102,7 @@ namespace gridfire::policy { * for (const auto &s : seeds) { std::cout << s.name() << std::endl; } * @endcode */ - [[nodiscard]] virtual const std::set get_seed_species() const = 0; + [[nodiscard]] virtual const std::set& get_seed_species() const = 0; /** * @brief Returns the set of seed reactions the policy requires. @@ -114,9 +113,9 @@ namespace gridfire::policy { * * @par Example * @code - * const reaction::ReactionSet &reacs = policy.get_seed_reactions(); + * const reaction::ReactionSet &reactions = policy.get_seed_reactions(); * // inspect reaction IDs or count - * std::cout << "Policy requires " << reacs.size() << " reactions" << std::endl; + * std::cout << "Policy requires " << reactions.size() << " reactions" << std::endl; * @endcode */ [[nodiscard]] virtual const reaction::ReactionSet& get_seed_reactions() const = 0; @@ -170,7 +169,7 @@ namespace gridfire::policy { * @par Example * @code * ProtonProtonChainPolicy pp; - * const auto &reacs = pp.get_reactions(); + * const gridfire::reaction::ReactionSet& reactions = pp.get_reactions(); * @endcode * * @note Concrete implementations may throw exceptions on construction if the underlying reaction @@ -195,28 +194,23 @@ namespace gridfire::policy { * at construction time if the required reactions cannot be found in the base reaction set. */ [[nodiscard]] virtual const reaction::ReactionSet& get_reactions() const = 0; + + [[nodiscard]] virtual bool contains(const std::string& id) const = 0; + [[nodiscard]] virtual bool contains(const reaction::Reaction& reaction) const = 0; + + [[nodiscard]] virtual std::unique_ptr clone() const = 0; + + [[nodiscard]] virtual std::string name() const = 0; + + [[nodiscard]] virtual uint64_t hash(uint64_t seed) const = 0; + + [[nodiscard]] virtual bool operator==(const ReactionChainPolicy& other) const = 0; + [[nodiscard]] virtual bool operator!=(const ReactionChainPolicy& other) const = 0; + + friend std::ostream& operator<<(std::ostream& os, const ReactionChainPolicy& rcp) { + os << "(ReactionChainPolicy: " << rcp.name() << ")"; + return os; + } }; - /** - * @class MultiReactionChainPolicy - * @brief A ReactionChainPolicy composed of multiple child ReactionChainPolicy instances. - * - * Useful for policies that represent a union of several reaction chains (for example the - * `LowMassMainSequenceReactionChainPolicy` composes the proton-proton and CNO chains). - * - * @par Example - * @code - * LowMassMainSequenceReactionChainPolicy multi; - * const auto &chains = multi.get_chain_policies(); - * for (const auto &ch : chains) { std::cout << ch->get_reactions().size() << " reactions\n"; } - * @endcode - */ - class MultiReactionChainPolicy : public ReactionChainPolicy { - public: - /** - * @brief Returns the vector of child ReactionChainPolicy instances. - * @return const std::vector>& - */ - [[nodiscard]] virtual const std::vector>& get_chain_policies() const = 0; - }; } diff --git a/src/include/gridfire/policy/policy_logical.h b/src/include/gridfire/policy/policy_logical.h index e69de29b..ba79d613 100644 --- a/src/include/gridfire/policy/policy_logical.h +++ b/src/include/gridfire/policy/policy_logical.h @@ -0,0 +1,51 @@ +#pragma once + +#include "gridfire/policy/policy_abstract.h" + +#include +#include + +namespace gridfire::policy { + /** + * @class MultiReactionChainPolicy + * @brief A ReactionChainPolicy composed of multiple child ReactionChainPolicy instances. + * + * Useful for policies that represent a union of several reaction chains (for example the + * `LowMassMainSequenceReactionChainPolicy` composes the proton-proton and CNO chains). + * + * @par Example + * @code + * LowMassMainSequenceReactionChainPolicy multi; + * const auto &chains = multi.get_chain_policies(); + * for (const auto &ch : chains) { std::cout << ch->get_reactions().size() << " reactions\n"; } + * @endcode + */ + class MultiReactionChainPolicy : public ReactionChainPolicy { + public: + explicit MultiReactionChainPolicy(std::vector>&& chain_policies); + + [[nodiscard]] const std::vector>& get_chain_policies() const; + + [[nodiscard]] const reaction::ReactionSet& get_reactions() const override; + + [[nodiscard]] bool contains(const std::string &id) const override; + [[nodiscard]] bool contains(const reaction::Reaction &reaction) const override; + + [[nodiscard]] std::unique_ptr clone() const override; + [[nodiscard]] std::string name() const override; + [[nodiscard]] uint64_t hash(uint64_t seed) const override; + + [[nodiscard]] bool operator==(const ReactionChainPolicy& other) const override; + [[nodiscard]] bool operator!=(const ReactionChainPolicy& other) const override; + + [[nodiscard]] size_t size() const; + + auto begin() { return m_chain_policies.begin(); } + [[nodiscard]] auto begin() const { return m_chain_policies.cbegin(); } + auto end() { return m_chain_policies.end(); } + [[nodiscard]] auto end() const { return m_chain_policies.cend(); } + protected: + std::vector> m_chain_policies; + reaction::ReactionSet m_reactions; + }; +} \ No newline at end of file diff --git a/src/include/gridfire/policy/stellar_policy.h b/src/include/gridfire/policy/stellar_policy.h index 62324c62..3ce8dd81 100644 --- a/src/include/gridfire/policy/stellar_policy.h +++ b/src/include/gridfire/policy/stellar_policy.h @@ -2,7 +2,7 @@ * @file stellar_policy.h * @brief High-level concrete NetworkPolicy for specific stellar environments. * - * This file defines the `LowMassMainSequencePolicy`, a concrete implementation of the `NetworkPolicy` + * This file defines the `MainSequencePolicy`, a concrete implementation of the `NetworkPolicy` * interface. This policy is designed to construct a reaction network suitable for simulating * nucleosynthesis in low-mass main-sequence stars (like the Sun). * @@ -23,21 +23,16 @@ #include "gridfire/engine/engine_abstract.h" #include "gridfire/reaction/reaction.h" -#include "gridfire/exceptions/error_policy.h" #include "fourdst/composition/composition.h" #include "fourdst/composition/atomicSpecies.h" -#include "fourdst/composition/exceptions/exceptions_composition.h" -#include "gridfire/engine/engine_graph.h" -#include "gridfire/engine/views/engine_adaptive.h" -#include "gridfire/engine/views/engine_multiscale.h" #include "gridfire/partition/composite/partition_composite.h" #include "gridfire/policy/chains.h" namespace gridfire::policy { /** - * @class LowMassMainSequencePolicy + * @class MainSequencePolicy * @brief A NetworkPolicy for building reaction networks suitable for low-mass main-sequence stars. * * This policy ensures that a constructed network contains all necessary species and reactions @@ -62,7 +57,7 @@ namespace gridfire::policy { * This policy composes the `ProtonProtonChainPolicy` and `CNOChainPolicy` to define * the required reactions. */ - class LowMassMainSequencePolicy final: public NetworkPolicy { + class MainSequencePolicy final: public NetworkPolicy { public: /** * @brief Constructs the policy from an existing composition object. @@ -78,7 +73,7 @@ namespace gridfire::policy { * LowMassMainSequencePolicy policy(comp); * @endcode */ - explicit LowMassMainSequencePolicy(const fourdst::composition::Composition& composition); + explicit MainSequencePolicy(const fourdst::composition::Composition& composition); /** * @brief Constructs the policy from a list of species and their mass fractions. * @@ -96,19 +91,19 @@ namespace gridfire::policy { * LowMassMainSequencePolicy policy(species, mass_fractions); * @endcode */ - explicit LowMassMainSequencePolicy(std::vector seed_species, std::vector mass_fractions); + explicit MainSequencePolicy(std::vector seed_species, std::vector mass_fractions); /** * @brief Returns the name of the policy. - * @return "LowMassMainSequencePolicy" + * @return "MainSequencePolicy" */ - [[nodiscard]] std::string name() const override { return "LowMassMainSequencePolicy"; } + [[nodiscard]] std::string name() const override { return "MainSequencePolicy"; } /** * @brief Returns the set of seed species required by this policy. * @return const std::set& */ - [[nodiscard]] const std::set get_seed_species() const override { return m_seed_species; } + [[nodiscard]] const std::set& get_seed_species() const override { return m_seed_species; } /** * @brief Returns the set of seed reactions required by this policy (from the PP and CNO chains). * @return const reaction::ReactionSet& @@ -159,7 +154,7 @@ namespace gridfire::policy { fourdst::atomic::Mg_24 }; - std::unique_ptr m_reaction_policy = std::make_unique(); + std::unique_ptr m_reaction_policy = std::make_unique(); fourdst::composition::Composition m_initializing_composition; std::unique_ptr m_partition_function; std::vector> m_network_stack; @@ -171,95 +166,6 @@ namespace gridfire::policy { }; - inline LowMassMainSequencePolicy::LowMassMainSequencePolicy(const fourdst::composition::Composition& composition) { - for (const auto& species : m_seed_species) { - if (!composition.hasSpecies(species)) { - throw exceptions::MissingSeedSpeciesError("Cannot initialize LowMassMainSequencePolicy: Required Seed species " + std::string(species.name()) + " is missing from the provided composition."); - } - } - m_initializing_composition = composition; - m_partition_function = build_partition_function(); - } - - inline LowMassMainSequencePolicy::LowMassMainSequencePolicy(std::vector seed_species, std::vector mass_fractions) { - for (const auto& species : m_seed_species) { - if (std::ranges::find(seed_species, species) == seed_species.end()) { - throw exceptions::MissingSeedSpeciesError("Cannot initialize LowMassMainSequencePolicy: Required Seed species " + std::string(species.name()) + " is missing from the provided composition."); - } - } - - for (const auto& [species, x] : std::views::zip(seed_species, mass_fractions)) { - m_initializing_composition.registerSpecies(species); - m_initializing_composition.setMassFraction(species, x); - } - - const bool didFinalize = m_initializing_composition.finalize(true); - if (!didFinalize) { - throw fourdst::composition::exceptions::CompositionNotFinalizedError("Failed to finalize initial composition for LowMassMainSequencePolicy."); - } - - m_partition_function = build_partition_function(); - } - - inline DynamicEngine& LowMassMainSequencePolicy::construct() { - m_network_stack.clear(); - - m_network_stack.emplace_back( - std::make_unique(m_initializing_composition, *m_partition_function, NetworkBuildDepth::ThirdOrder, NetworkConstructionFlags::DEFAULT) - ); - m_network_stack.emplace_back( - std::make_unique(*m_network_stack.back().get()) - ); - m_network_stack.emplace_back( - std::make_unique(*m_network_stack.back().get()) - ); - - m_status = NetworkPolicyStatus::INITIALIZED_UNVERIFIED; - m_status = check_status(); - - switch (m_status) { - case NetworkPolicyStatus::MISSING_KEY_REACTION: - throw exceptions::MissingKeyReactionError("LowMassMainSequencePolicy construction failed: The constructed network is missing key reactions required by the policy."); - case NetworkPolicyStatus::MISSING_KEY_SPECIES: - throw exceptions::MissingSeedSpeciesError("LowMassMainSequencePolicy construction failed: The constructed network is missing key seed species required by the policy."); - case NetworkPolicyStatus::UNINITIALIZED: - throw exceptions::PolicyError("LowMassMainSequencePolicy construction failed: The network policy is uninitialized."); - case NetworkPolicyStatus::INITIALIZED_UNVERIFIED: - throw exceptions::PolicyError("LowMassMainSequencePolicy construction failed: The network policy status could not be verified."); - case NetworkPolicyStatus::INITIALIZED_VERIFIED: - break; - } - return *m_network_stack.back(); - } - - inline std::unique_ptr LowMassMainSequencePolicy::build_partition_function() { - using partition::BasePartitionType; - const auto partitionFunction = partition::CompositePartitionFunction({ - BasePartitionType::RauscherThielemann, - BasePartitionType::GroundState - }); - return std::make_unique(partitionFunction); - } - - inline NetworkPolicyStatus LowMassMainSequencePolicy::getStatus() const { - return m_status; - } - - inline NetworkPolicyStatus LowMassMainSequencePolicy::check_status() const { - for (const auto& species : m_seed_species) { - if (!m_initializing_composition.hasSpecies(species)) { - return NetworkPolicyStatus::MISSING_KEY_SPECIES; - } - } - const reaction::ReactionSet& baseReactions = m_network_stack.front()->getNetworkReactions(); - for (const auto& reaction : m_reaction_policy->get_reactions()) { - const bool result = baseReactions.contains(*reaction); - if (!result) { - return NetworkPolicyStatus::MISSING_KEY_REACTION; - } - } - return NetworkPolicyStatus::INITIALIZED_VERIFIED; - } } \ No newline at end of file diff --git a/src/include/gridfire/reaction/reaction.h b/src/include/gridfire/reaction/reaction.h index a6e46e94..d7444369 100644 --- a/src/include/gridfire/reaction/reaction.h +++ b/src/include/gridfire/reaction/reaction.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -345,7 +344,7 @@ namespace gridfire::reaction { return os; } - virtual std::optional> getRateCoefficients() const = 0; + [[nodiscard]] virtual std::optional> getRateCoefficients() const = 0; }; class ReaclibReaction : public Reaction { diff --git a/src/include/gridfire/utils/hashing.h b/src/include/gridfire/utils/hashing.h index 66eee8f3..0905ada9 100644 --- a/src/include/gridfire/utils/hashing.h +++ b/src/include/gridfire/utils/hashing.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "gridfire/exceptions/exceptions.h" #include "gridfire/reaction/reaction.h" @@ -62,4 +63,10 @@ namespace gridfire::utils { return splitmix64(h); } + template + std::size_t hash_combine(std::size_t seed, const T& v) { + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } } diff --git a/src/lib/policy/chains.cpp b/src/lib/policy/chains.cpp index e69de29b..b0be96ca 100644 --- a/src/lib/policy/chains.cpp +++ b/src/lib/policy/chains.cpp @@ -0,0 +1,337 @@ +#include "gridfire/policy/policy_abstract.h" +#include "gridfire/policy/policy_logical.h" +#include "gridfire/policy/chains.h" + +#include "gridfire/exceptions/error_policy.h" + +#include "gridfire/utils/hashing.h" +#include "gridfire/reaction/reaclib.h" + +#include "xxhash64.h" + + +namespace gridfire::policy { + TemperatureDependentChainPolicy::TemperatureDependentChainPolicy( + const std::vector& reactionIDs + ) : TemperatureDependentChainPolicy(reactionIDs, std::nullopt, std::nullopt) {} + + TemperatureDependentChainPolicy::TemperatureDependentChainPolicy( + const std::vector& reactionIDs, + const std::optional minT9 + ) : TemperatureDependentChainPolicy(reactionIDs, minT9, std::nullopt) {} + + TemperatureDependentChainPolicy::TemperatureDependentChainPolicy( + const std::vector& reactionIDs, + const std::optional minT9, + const std::optional maxT9 + ) : + m_reactionIDs(reactionIDs) + { + m_tempRange.minT9 = minT9; + m_tempRange.maxT9 = maxT9; + + const auto& all_reaclib_reactions = reaclib::get_all_reaclib_reactions(); + + for (const auto& reactionID : m_reactionIDs) { + auto reaction = all_reaclib_reactions.get(reactionID); + if (!reaction) { + throw exceptions::MissingBaseReactionError("The Underlying REACLIB reaction set is missing the reaction " + std::string(reactionID) + " needed for a chain. This indicates that there is an issue with the GridFire binary you are using. Please try to recompile and if that fails please report this issue to the developers."); + } + m_reactions.add_reaction(reaction.value()->clone()); + } + } + + const reaction::ReactionSet& TemperatureDependentChainPolicy::get_reactions() const { + return m_reactions; + } + + bool TemperatureDependentChainPolicy::contains(const std::string &id) const { + return m_reactions.contains(id); + } + + bool TemperatureDependentChainPolicy::contains(const reaction::Reaction &reaction) const { + return m_reactions.contains(reaction); + } + + uint64_t TemperatureDependentChainPolicy::hash(const uint64_t seed) const { + std::vector hashes; + for (const auto& reaction : m_reactions) { + hashes.push_back(reaction->hash(seed)); + } + return XXHash64::hash(hashes.data(), hashes.size(), seed); + } + + bool TemperatureDependentChainPolicy::operator==(const ReactionChainPolicy &other) const { + return this->hash(0) == other.hash(0); + } + + bool TemperatureDependentChainPolicy::operator!=(const ReactionChainPolicy &other) const { + return this->hash(0) != other.hash(0); + } + + bool TemperatureDependentChainPolicy::is_active(const double T9) const { + return (!m_tempRange.minT9.has_value() || T9 >= m_tempRange.minT9.value()) && + (!m_tempRange.maxT9.has_value() || T9 <= m_tempRange.maxT9.value()); + } + + /** + * Specific Implementations * + **/ + + ProtonProtonIChainPolicy::ProtonProtonIChainPolicy() + : TemperatureDependentChainPolicy({ + // Proton-Proton I + "p(p,e+)d", + "d(p,g)he3", + "he3(he3,2p)he4", + },0.001) {} + + ProtonProtonIIChainPolicy::ProtonProtonIIChainPolicy() + : TemperatureDependentChainPolicy({ + "p(p,e+)d", + "d(p,g)he3", + "he4(he3,g)be7", + "be7(e-,)li7", + "li7(p,a)he4", + }, 0.001) {} + + ProtonProtonIIIChainPolicy::ProtonProtonIIIChainPolicy() + : TemperatureDependentChainPolicy({ + "p(p,e+)d", + "d(p,g)he3", + "he4(he3,g)be7", + "be7(p,g)b8", + "b8(,e+)be8", + "be8(,a)he4" + }, 0.001) {} + + std::unique_ptr ProtonProtonIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string ProtonProtonIChainPolicy::name() const { + return "ProtonProtonIChainPolicy"; + } + + + std::unique_ptr ProtonProtonIIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string ProtonProtonIIChainPolicy::name() const { + return "ProtonProtonIIChainPolicy"; + } + + + std::unique_ptr ProtonProtonIIIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string ProtonProtonIIIChainPolicy::name() const { + return "ProtonProtonIIIChainPolicy"; + } + + ProtonProtonChainPolicy::ProtonProtonChainPolicy() : + MultiReactionChainPolicy( + []() { + std::vector> chain_policies; + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + return chain_policies; + }() + ){} + + std::string ProtonProtonChainPolicy::name() const { + return "ProtonProtonChainPolicy"; + } + + CNOIChainPolicy::CNOIChainPolicy() + : TemperatureDependentChainPolicy({ + "c12(p,g)n13", + "n13(,e+)c13", + "c13(p,g)n14", + "n14(p,g)o15", + "o15(,e+)n15", + "n15(p,a)c12", + }, 0.001){} + + CNOIIChainPolicy::CNOIIChainPolicy() + : TemperatureDependentChainPolicy({ + "n15(p,g)o16", + "o16(p,g)f17", + "f17(,e+)o17", + "o17(p,a)n14", + "n14(p,g)o15", + "o15(,e+)n15", + }, 0.001){} + + CNOIIIChainPolicy::CNOIIIChainPolicy() + : TemperatureDependentChainPolicy({ + "o17(p,g)f18", + "f18(,e+)o18", + "o18(p,a)n15", + "n15(p,g)o16", + "o16(p,g)f17", + "f17(,e+)o17", + }, 0.001){} + + CNOIVChainPolicy::CNOIVChainPolicy() + : TemperatureDependentChainPolicy({ + "o18(p,g)f19", + "f19(p,a)o16", + "o16(p,g)f17", + "f17(,e+)o17", + "o17(p,g)f18", + "f18(,e+)o18" + }, 0.001){} + + + std::unique_ptr CNOIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string CNOIChainPolicy::name() const { + return "CNOIChainPolicy"; + } + + std::unique_ptr CNOIIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string CNOIIChainPolicy::name() const { + return "CNOIIChainPolicy"; + } + + std::unique_ptr CNOIIIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string CNOIIIChainPolicy::name() const { + return "CNOIIIChainPolicy"; + } + + std::unique_ptr CNOIVChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string CNOIVChainPolicy::name() const { + return "CNOIVChainPolicy"; + } + + CNOChainPolicy::CNOChainPolicy() : + MultiReactionChainPolicy( + []() { + std::vector> chain_policies; + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + + return chain_policies; + }() + ){} + + std::string CNOChainPolicy::name() const { + return "CNOChainPolicy"; + } + + HotCNOIChainPolicy::HotCNOIChainPolicy() + : TemperatureDependentChainPolicy({ + "c12(p,g)n13", + "n13(p,g)o14", + "o14(,e+)n14", + "n14(p,g)o15", + "o15(,e+)n15", + "n15(p,a)c12", + }, 0.1) {} + + HotCNOIIChainPolicy::HotCNOIIChainPolicy() + : TemperatureDependentChainPolicy({ + "n15(p,g)o16", + "o16(p,g)f17", + "f17(p,g)ne18", + "ne18(,e+)f18", + "f18(p,a)o15", + "o15(,e+)n15", + }, 0.1) {} + + HotCNOIIIChainPolicy::HotCNOIIIChainPolicy() + : TemperatureDependentChainPolicy({ + "f18(p,g)ne19", + "ne19(,e+)f19", + "f19(p,a)o16", + "o16(p,g)f17", + "f17(p,g)ne18", + "ne18(,e+)f18" + }, 0.1) {} + + std::unique_ptr HotCNOIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string HotCNOIChainPolicy::name() const { + return "HotCNOIChainPolicy"; + } + + std::unique_ptr HotCNOIIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string HotCNOIIChainPolicy::name() const { + return "HotCNOIIChainPolicy"; + } + + std::unique_ptr HotCNOIIIChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string HotCNOIIIChainPolicy::name() const { + return "HotCNOIIIChainPolicy"; + } + + HotCNOChainPolicy::HotCNOChainPolicy() + : MultiReactionChainPolicy( + []() { + std::vector> chain_policies; + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + + return chain_policies; + }() + ){} + + std::string HotCNOChainPolicy::name() const { + return "HotCNOChainPolicy"; + } + + TripleAlphaChainPolicy::TripleAlphaChainPolicy() + : TemperatureDependentChainPolicy({ + "he4(he4,a)be8", + "be8(he4,g)c12" + }, 0.01) {} + + std::unique_ptr TripleAlphaChainPolicy::clone() const { + return std::make_unique(*this); + } + + std::string TripleAlphaChainPolicy::name() const { + return "TripleAlphaChainPolicy"; + } + + MainSequenceReactionChainPolicy::MainSequenceReactionChainPolicy() + : MultiReactionChainPolicy( + []() { + std::vector> chain_policies; + chain_policies.push_back(std::make_unique()); + chain_policies.push_back(std::make_unique()); + + return chain_policies; + }() + ){} + + std::string MainSequenceReactionChainPolicy::name() const { + return "MainSequenceReactionChainPolicy"; + } +} diff --git a/src/lib/policy/policy_logical.cpp b/src/lib/policy/policy_logical.cpp index e69de29b..e99a0052 100644 --- a/src/lib/policy/policy_logical.cpp +++ b/src/lib/policy/policy_logical.cpp @@ -0,0 +1,69 @@ +#include "gridfire/policy/policy_abstract.h" +#include "gridfire/policy/policy_logical.h" + +#include "xxhash64.h" +#include "gridfire/utils/hashing.h" + +namespace gridfire::policy { + MultiReactionChainPolicy::MultiReactionChainPolicy( + std::vector> &&chain_policies + ) : m_chain_policies(std::move(chain_policies)) { + for (const auto &ch : m_chain_policies) { + m_reactions.extend(ch->get_reactions()); + } + } + + const std::vector> & MultiReactionChainPolicy::get_chain_policies() const { + return m_chain_policies; + } + + const reaction::ReactionSet & MultiReactionChainPolicy::get_reactions() const { + return m_reactions; + } + + bool MultiReactionChainPolicy::contains(const std::string &id) const { + return m_reactions.contains(id); + } + + bool MultiReactionChainPolicy::contains(const reaction::Reaction &reaction) const { + return m_reactions.contains(reaction); + } + + std::unique_ptr MultiReactionChainPolicy::clone() const { + return std::make_unique( + [this]() { + std::vector> chain_policies; + for (const auto &ch : m_chain_policies) { + chain_policies.push_back(ch->clone()); + } + return chain_policies; + }() + ); + } + + std::string MultiReactionChainPolicy::name() const { + return "MultiReactionChainPolicy"; + } + + uint64_t MultiReactionChainPolicy::hash(const uint64_t seed) const { + std::vector reaction_hashes; + for (const auto& reaction : m_reactions) { + reaction_hashes.push_back(reaction->hash(seed)); + } + + return XXHash64::hash(reaction_hashes.data(), reaction_hashes.size(), seed); + } + + bool MultiReactionChainPolicy::operator==(const ReactionChainPolicy &other) const { + return this->hash(0) == other.hash(0); + } + + bool MultiReactionChainPolicy::operator!=(const ReactionChainPolicy &other) const { + return this->hash(0) != other.hash(0); + } + + + size_t MultiReactionChainPolicy::size() const { + return m_chain_policies.size(); + } +} diff --git a/src/lib/policy/stellar_policy.cpp b/src/lib/policy/stellar_policy.cpp index e69de29b..caeb2cc3 100644 --- a/src/lib/policy/stellar_policy.cpp +++ b/src/lib/policy/stellar_policy.cpp @@ -0,0 +1,101 @@ +#include "gridfire/policy/stellar_policy.h" +#include "gridfire/policy/policy_abstract.h" +#include "gridfire/exceptions/error_policy.h" + +#include "gridfire/engine/engine_abstract.h" +#include "gridfire/engine/engine_graph.h" +#include "gridfire/engine/views/engine_views.h" + +#include "fourdst/composition/exceptions/exceptions_composition.h" + +namespace gridfire::policy { + MainSequencePolicy::MainSequencePolicy(const fourdst::composition::Composition& composition) { + for (const auto& species : m_seed_species) { + if (!composition.hasSpecies(species)) { + throw exceptions::MissingSeedSpeciesError("Cannot initialize MainSequencePolicy: Required Seed species " + std::string(species.name()) + " is missing from the provided composition."); + } + } + m_initializing_composition = composition; + m_partition_function = build_partition_function(); + } + + MainSequencePolicy::MainSequencePolicy(std::vector seed_species, std::vector mass_fractions) { + for (const auto& species : m_seed_species) { + if (std::ranges::find(seed_species, species) == seed_species.end()) { + throw exceptions::MissingSeedSpeciesError("Cannot initialize MainSequencePolicy: Required Seed species " + std::string(species.name()) + " is missing from the provided composition."); + } + } + + for (const auto& [species, x] : std::views::zip(seed_species, mass_fractions)) { + m_initializing_composition.registerSpecies(species); + m_initializing_composition.setMassFraction(species, x); + } + + const bool didFinalize = m_initializing_composition.finalize(true); + if (!didFinalize) { + throw fourdst::composition::exceptions::CompositionNotFinalizedError("Failed to finalize initial composition for MainSequencePolicy."); + } + + m_partition_function = build_partition_function(); + } + + DynamicEngine& MainSequencePolicy::construct() { + m_network_stack.clear(); + + m_network_stack.emplace_back( + std::make_unique(m_initializing_composition, *m_partition_function, NetworkBuildDepth::ThirdOrder, NetworkConstructionFlags::DEFAULT) + ); + m_network_stack.emplace_back( + std::make_unique(*m_network_stack.back().get()) + ); + m_network_stack.emplace_back( + std::make_unique(*m_network_stack.back().get()) + ); + + m_status = NetworkPolicyStatus::INITIALIZED_UNVERIFIED; + m_status = check_status(); + + switch (m_status) { + case NetworkPolicyStatus::MISSING_KEY_REACTION: + throw exceptions::MissingKeyReactionError("MainSequencePolicy construction failed: The constructed network is missing key reactions required by the policy."); + case NetworkPolicyStatus::MISSING_KEY_SPECIES: + throw exceptions::MissingSeedSpeciesError("MainSequencePolicy construction failed: The constructed network is missing key seed species required by the policy."); + case NetworkPolicyStatus::UNINITIALIZED: + throw exceptions::PolicyError("MainSequencePolicy construction failed: The network policy is uninitialized."); + case NetworkPolicyStatus::INITIALIZED_UNVERIFIED: + throw exceptions::PolicyError("MainSequencePolicy construction failed: The network policy status could not be verified."); + case NetworkPolicyStatus::INITIALIZED_VERIFIED: + break; + } + return *m_network_stack.back(); + } + + inline std::unique_ptr MainSequencePolicy::build_partition_function() { + using partition::BasePartitionType; + const auto partitionFunction = partition::CompositePartitionFunction({ + BasePartitionType::RauscherThielemann, + BasePartitionType::GroundState + }); + return std::make_unique(partitionFunction); + } + + inline NetworkPolicyStatus MainSequencePolicy::getStatus() const { + return m_status; + } + + inline NetworkPolicyStatus MainSequencePolicy::check_status() const { + for (const auto& species : m_seed_species) { + if (!m_initializing_composition.hasSpecies(species)) { + return NetworkPolicyStatus::MISSING_KEY_SPECIES; + } + } + const reaction::ReactionSet& baseReactions = m_network_stack.front()->getNetworkReactions(); + for (const auto& reaction : m_reaction_policy->get_reactions()) { + const bool result = baseReactions.contains(*reaction); + if (!result) { + return NetworkPolicyStatus::MISSING_KEY_REACTION; + } + } + return NetworkPolicyStatus::INITIALIZED_VERIFIED; + } +} \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index ab46604f..0406e589 100644 --- a/src/meson.build +++ b/src/meson.build @@ -24,6 +24,9 @@ gridfire_sources = files( 'lib/partition/partition_rauscher_thielemann.cpp', 'lib/partition/partition_ground.cpp', 'lib/partition/composite/partition_composite.cpp', + 'lib/policy/chains.cpp', + 'lib/policy/policy_logical.cpp', + 'lib/policy/stellar_policy.cpp', 'lib/utils/logging.cpp', )