GridFire 0.0.1a
General Purpose Nuclear Network
Loading...
Searching...
No Matches
engine_multiscale.h
Go to the documentation of this file.
1#pragma once
2
6
7#include "unsupported/Eigen/NonLinearOptimization"
8
9namespace gridfire {
28 double T9_tol;
29 double rho_tol;
30 double Yi_tol;
31 };
32
47 struct QSECacheKey {
48 double m_T9;
49 double m_rho;
50 std::vector<double> m_Y;
51
52 std::size_t m_hash = 0;
53
54 // TODO: We should probably sort out how to adjust these from absolute to relative tolerances.
56 1e-3, // Default tolerance for T9
57 1e-1, // Default tolerance for rho
58 1e-3 // Default tolerance for species abundances
59 };
60
71 const double T9,
72 const double rho,
73 const std::vector<double>& Y
74 );
75
84 size_t hash() const;
85
94 static long bin(double value, double tol);
95
101 bool operator==(const QSECacheKey& other) const;
102
103 };
104}
105
106// Needs to be in this order (splitting gridfire namespace up) to avoid some issues with forward declarations and the () operator.
107namespace std {
108 template <>
109 struct hash<gridfire::QSECacheKey> {
115 size_t operator()(const gridfire::QSECacheKey& key) const noexcept {
116 // The hash is pre-computed, so we just return it.
117 return key.m_hash;
118 }
119 };
120} // namespace std
121
122namespace gridfire {
174 class MultiscalePartitioningEngineView final: public DynamicEngine, public EngineView<DynamicEngine> {
181 typedef std::tuple<std::vector<fourdst::atomic::Species>, std::vector<size_t>, std::vector<fourdst::atomic::Species>, std::vector<size_t>> QSEPartition;
182 public:
190 explicit MultiscalePartitioningEngineView(GraphEngine& baseEngine);
191
198 [[nodiscard]] const std::vector<fourdst::atomic::Species> & getNetworkSpecies() const override;
199
225 [[nodiscard]] std::expected<StepDerivatives<double>, expectations::StaleEngineError> calculateRHSAndEnergy(
226 const std::vector<double> &Y_full,
227 double T9,
228 double rho
229 ) const override;
230
253 const std::vector<double> &Y_full,
254 double T9,
255 double rho
256 ) const override;
257
273 [[nodiscard]] double getJacobianMatrixEntry(
274 int i_full,
275 int j_full
276 ) const override;
277
286 void generateStoichiometryMatrix() override;
287
301 [[nodiscard]] int getStoichiometryMatrixEntry(
302 int speciesIndex,
303 int reactionIndex
304 ) const override;
305
326 [[nodiscard]] double calculateMolarReactionFlow(
328 const std::vector<double> &Y_full,
329 double T9,
330 double rho
331 ) const override;
332
339 [[nodiscard]] const reaction::LogicalReactionSet & getNetworkReactions() const override;
340
356 const reaction::LogicalReactionSet &reactions
357 ) override;
358
377 [[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesTimescales(
378 const std::vector<double> &Y,
379 double T9,
380 double rho
381 ) const override;
382
401 [[nodiscard]] std::expected<std::unordered_map<fourdst::atomic::Species, double>, expectations::StaleEngineError> getSpeciesDestructionTimescales(
402 const std::vector<double> &Y,
403 double T9,
404 double rho
405 ) const override;
406
433 fourdst::composition::Composition update(
434 const NetIn &netIn
435 ) override;
436
450 bool isStale(const NetIn& netIn) override;
451
461 ) override;
462
470 [[nodiscard]] screening::ScreeningType getScreeningModel() const override;
471
477 const DynamicEngine & getBaseEngine() const override;
478
497 std::vector<std::vector<size_t>> analyzeTimescalePoolConnectivity(
498 const std::vector<std::vector<size_t>> &timescale_pools,
499 const std::vector<double> &Y,
500 double T9,
501 double rho
502 ) const;
503
531 void partitionNetwork(
532 const std::vector<double>& Y,
533 double T9,
534 double rho
535 );
536
547 void partitionNetwork(
548 const NetIn& netIn
549 );
550
564 void exportToDot(
565 const std::string& filename,
566 const std::vector<double>& Y,
567 const double T9,
568 const double rho
569 ) const;
570
579 [[nodiscard]] int getSpeciesIndex(const fourdst::atomic::Species &species) const override;
580
589 [[nodiscard]] std::vector<double> mapNetInToMolarAbundanceVector(const NetIn &netIn) const override;
590
602 [[nodiscard]] PrimingReport primeEngine(const NetIn &netIn) override;
603
615 [[nodiscard]] std::vector<fourdst::atomic::Species> getFastSpecies() const;
627 [[nodiscard]] const std::vector<fourdst::atomic::Species>& getDynamicSpecies() const;
628
648 fourdst::composition::Composition equilibrateNetwork(
649 const std::vector<double> &Y,
650 double T9,
651 double rho
652 );
653
665 fourdst::composition::Composition equilibrateNetwork(
666 const NetIn &netIn
667 );
668
669
670 private:
677 struct QSEGroup {
678 std::set<size_t> species_indices;
679 bool is_in_equilibrium = false;
680 std::set<size_t> algebraic_indices;
681 std::set<size_t> seed_indices;
683
689 bool operator<(const QSEGroup& other) const;
695 bool operator>(const QSEGroup& other) const;
701 bool operator==(const QSEGroup& other) const;
707 bool operator!=(const QSEGroup& other) const;
708 };
709
730 using InputType = Eigen::Matrix<double, Eigen::Dynamic, 1>;
731 using OutputType = Eigen::Matrix<double, Eigen::Dynamic, 1>;
732 using JacobianType = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
733 enum {
734 InputsAtCompileTime = Eigen::Dynamic,
735 ValuesAtCompileTime = Eigen::Dynamic
736 };
737
745 const std::vector<size_t>& m_qse_solve_indices;
749 const std::vector<double>& m_Y_full_initial;
753 const double m_T9;
757 const double m_rho;
761 const Eigen::VectorXd& m_Y_scale;
762
775 const std::vector<size_t>& qse_solve_indices,
776 const std::vector<double>& Y_full_initial,
777 const double T9,
778 const double rho,
779 const Eigen::VectorXd& Y_scale
780 ) :
781 m_view(&view),
782 m_qse_solve_indices(qse_solve_indices),
783 m_Y_full_initial(Y_full_initial),
784 m_T9(T9),
785 m_rho(rho),
786 m_Y_scale(Y_scale) {}
787
792 [[nodiscard]] int values() const { return m_qse_solve_indices.size(); }
797 [[nodiscard]] int inputs() const { return m_qse_solve_indices.size(); }
798
805 int operator()(const InputType& v_qse, OutputType& f_qse) const;
812 int df(const InputType& v_qse, JacobianType& J_qse) const;
813 };
814
815
822 struct CacheStats {
832
836 std::map<operators, std::string> operatorsNameMap = {
837 {operators::CalculateRHSAndEnergy, "calculateRHSAndEnergy"},
838 {operators::GenerateJacobianMatrix, "generateJacobianMatrix"},
839 {operators::CalculateMolarReactionFlow, "calculateMolarReactionFlow"},
840 {operators::GetSpeciesTimescales, "getSpeciesTimescales"},
841 {operators::GetSpeciesDestructionTimescales, "getSpeciesDestructionTimescales"},
842 {operators::Other, "other"}
843 };
844
848 size_t m_hit = 0;
852 size_t m_miss = 0;
853
865
877
883 void hit(const operators op=operators::Other);
889 void miss(const operators op=operators::Other);
890
896 [[nodiscard]] size_t hits(const operators op=operators::All) const;
902 [[nodiscard]] size_t misses(const operators op=operators::All) const;
903 };
904
905
906 private:
910 quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
918 std::vector<QSEGroup> m_qse_groups;
922 std::vector<fourdst::atomic::Species> m_dynamic_species;
926 std::vector<size_t> m_dynamic_species_indices;
930 std::vector<fourdst::atomic::Species> m_algebraic_species;
934 std::vector<size_t> m_algebraic_species_indices;
935
939 std::vector<size_t> m_activeSpeciesIndices;
943 std::vector<size_t> m_activeReactionIndices;
944
945 // TODO: Enhance the hashing for the cache to consider not just T and rho but also the current abundance in some careful way that automatically ignores small changes (i.e. network should only be repartitioned sometimes)
953 mutable std::unordered_map<QSECacheKey, std::vector<double>> m_qse_abundance_cache;
958
959
960
961
962 private:
979 std::vector<std::vector<size_t>> partitionByTimescale(
980 const std::vector<double> &Y_full,
981 double T9,
982 double rho
983 ) const;
984
998 std::unordered_map<size_t, std::vector<size_t>> buildConnectivityGraph(
999 const std::unordered_set<size_t> &fast_reaction_indices
1000 ) const;
1001
1020 std::vector<QSEGroup> validateGroupsWithFluxAnalysis(
1021 const std::vector<QSEGroup> &candidate_groups,
1022 const std::vector<double>& Y,
1023 double T9,
1024 double rho
1025 ) const;
1026
1045 std::vector<double> solveQSEAbundances(
1046 const std::vector<double> &Y_full,
1047 double T9,
1048 double rho
1049 );
1050
1067 const std::vector<std::vector<size_t>>& pools,
1068 const std::vector<double> &Y,
1069 double T9,
1070 double rho
1071 ) const;
1072
1086 std::unordered_map<size_t, std::vector<size_t>> buildConnectivityGraph(
1087 const std::vector<size_t>& species_pool
1088 ) const;
1089
1108 std::vector<QSEGroup> constructCandidateGroups(
1109 const std::vector<std::vector<size_t>>& candidate_pools,
1110 const std::vector<double>& Y,
1111 double T9,
1112 double rho
1113 ) const;
1114 };
1115}
1116
Abstract class for engines supporting Jacobian and stoichiometry operations.
Abstract base class for a "view" of a reaction network engine.
A reaction network engine that uses a graph-based representation.
GraphEngine & m_baseEngine
The base engine to which this view delegates calculations.
PrimingReport primeEngine(const NetIn &netIn) override
Primes the engine with a specific species.
MultiscalePartitioningEngineView(GraphEngine &baseEngine)
Constructs a MultiscalePartitioningEngineView.
void setScreeningModel(screening::ScreeningType model) override
Sets the electron screening model.
std::vector< QSEGroup > m_qse_groups
The list of identified equilibrium groups.
const std::vector< fourdst::atomic::Species > & getDynamicSpecies() const
Gets the dynamic species in the network.
const DynamicEngine & getBaseEngine() const override
Gets the base engine.
std::tuple< std::vector< fourdst::atomic::Species >, std::vector< size_t >, std::vector< fourdst::atomic::Species >, std::vector< size_t > > QSEPartition
Type alias for a QSE partition.
std::vector< size_t > m_dynamic_species_indices
Indices mapping the dynamic species back to the base engine's full species list.
std::vector< double > solveQSEAbundances(const std::vector< double > &Y_full, double T9, double rho)
Solves for the QSE abundances of the algebraic species in a given state.
std::vector< fourdst::atomic::Species > getFastSpecies() const
Gets the fast species in the network.
std::vector< size_t > m_activeReactionIndices
Indices of all reactions involving only active species.
std::vector< fourdst::atomic::Species > m_algebraic_species
Species that are treated as algebraic (in QSE) in the QSE groups.
fourdst::composition::Composition equilibrateNetwork(const std::vector< double > &Y, double T9, double rho)
Equilibrates the network by partitioning and solving for QSE abundances.
int getStoichiometryMatrixEntry(int speciesIndex, int reactionIndex) const override
Gets an entry from the stoichiometry matrix.
std::vector< size_t > m_algebraic_species_indices
Indices of algebraic species in the full network.
size_t identifyMeanSlowestPool(const std::vector< std::vector< size_t > > &pools, const std::vector< double > &Y, double T9, double rho) const
Identifies the pool with the slowest mean timescale.
std::expected< std::unordered_map< fourdst::atomic::Species, double >, expectations::StaleEngineError > getSpeciesTimescales(const std::vector< double > &Y, double T9, double rho) const override
Computes timescales for all species in the network.
std::vector< size_t > m_activeSpeciesIndices
Indices of all species considered active in the current partition (dynamic + algebraic).
const std::vector< fourdst::atomic::Species > & getNetworkSpecies() const override
Gets the list of species in the network.
fourdst::composition::Composition update(const NetIn &netIn) override
Updates the internal state of the engine, performing partitioning and QSE equilibration.
std::unordered_map< QSECacheKey, std::vector< double > > m_qse_abundance_cache
Cache for QSE abundances based on T9, rho, and Y.
std::expected< StepDerivatives< double >, expectations::StaleEngineError > calculateRHSAndEnergy(const std::vector< double > &Y_full, double T9, double rho) const override
Calculates the right-hand side (dY/dt) and energy generation.
double calculateMolarReactionFlow(const reaction::Reaction &reaction, const std::vector< double > &Y_full, double T9, double rho) const override
Calculates the molar reaction flow for a given reaction.
screening::ScreeningType getScreeningModel() const override
Gets the current electron screening model.
void partitionNetwork(const std::vector< double > &Y, double T9, double rho)
Partitions the network into dynamic and algebraic (QSE) groups based on timescales.
quill::Logger * m_logger
Logger instance for logging messages.
int getSpeciesIndex(const fourdst::atomic::Species &species) const override
Gets the index of a species in the full network.
std::expected< std::unordered_map< fourdst::atomic::Species, double >, expectations::StaleEngineError > getSpeciesDestructionTimescales(const std::vector< double > &Y, double T9, double rho) const override
Computes destruction timescales for all species in the network.
std::vector< QSEGroup > validateGroupsWithFluxAnalysis(const std::vector< QSEGroup > &candidate_groups, const std::vector< double > &Y, double T9, double rho) const
Validates candidate QSE groups using flux analysis.
CacheStats m_cacheStats
Statistics for the QSE abundance cache.
std::vector< double > mapNetInToMolarAbundanceVector(const NetIn &netIn) const override
Maps a NetIn struct to a molar abundance vector for the full network.
std::unordered_map< size_t, std::vector< size_t > > buildConnectivityGraph(const std::unordered_set< size_t > &fast_reaction_indices) const
Builds a connectivity graph from a set of fast reaction indices.
void generateStoichiometryMatrix() override
Generates the stoichiometry matrix for the network.
std::vector< QSEGroup > constructCandidateGroups(const std::vector< std::vector< size_t > > &candidate_pools, const std::vector< double > &Y, double T9, double rho) const
Constructs candidate QSE groups from connected timescale pools.
double getJacobianMatrixEntry(int i_full, int j_full) const override
Gets an entry from the previously generated Jacobian matrix.
void setNetworkReactions(const reaction::LogicalReactionSet &reactions) override
Sets the set of logical reactions in the network.
void generateJacobianMatrix(const std::vector< double > &Y_full, double T9, double rho) const override
Generates the Jacobian matrix for the current state.
void exportToDot(const std::string &filename, const std::vector< double > &Y, const double T9, const double rho) const
Exports the network to a DOT file for visualization.
std::vector< std::vector< size_t > > partitionByTimescale(const std::vector< double > &Y_full, double T9, double rho) const
Partitions the network by timescale.
const reaction::LogicalReactionSet & getNetworkReactions() const override
Gets the set of logical reactions in the network.
bool isStale(const NetIn &netIn) override
Checks if the engine's internal state is stale relative to the provided conditions.
std::vector< fourdst::atomic::Species > m_dynamic_species
The simplified set of species presented to the solver (the "slow" species).
std::vector< std::vector< size_t > > analyzeTimescalePoolConnectivity(const std::vector< std::vector< size_t > > &timescale_pools, const std::vector< double > &Y, double T9, double rho) const
Analyzes the connectivity of timescale pools.
Represents a single nuclear reaction from a specific data source.
Definition reaction.h:72
Abstract interfaces for reaction network engines in GridFire.
Abstract interfaces for engine "views" in GridFire.
TemplatedReactionSet< LogicalReaction > LogicalReactionSet
A set of logical reactions.
Definition reaction.h:563
ScreeningType
Enumerates the available plasma screening models.
STL namespace.
size_t misses(const operators op=operators::All) const
Gets the number of misses for a specific operator or all operators.
void hit(const operators op=operators::Other)
Increments the hit counter for a given operator.
size_t hits(const operators op=operators::All) const
Gets the number of hits for a specific operator or all operators.
std::map< operators,size_t > m_operatorHits
Map from operators to the number of cache hits for that operator.
void miss(const operators op=operators::Other)
Increments the miss counter for a given operator.
std::map< operators,std::string > operatorsNameMap
Map from operators to their string names for logging.
std::map< operators,size_t > m_operatorMisses
Map from operators to the number of cache misses for that operator.
int inputs() const
Gets the number of input values to the functor (size of the variable vector).
EigenFunctor(MultiscalePartitioningEngineView &view, const std::vector< size_t > &qse_solve_indices, const std::vector< double > &Y_full_initial, const double T9, const double rho, const Eigen::VectorXd &Y_scale)
Constructs an EigenFunctor.
const std::vector< double > & m_Y_full_initial
Initial abundances of all species in the full network.
Eigen::Matrix< double, Eigen::Dynamic, 1 > InputType
Eigen::Matrix< double, Eigen::Dynamic, 1 > OutputType
const std::vector< size_t > & m_qse_solve_indices
Indices of the species to solve for in the QSE group.
int values() const
Gets the number of output values from the functor (size of the residual vector).
const double m_T9
Temperature in units of 10^9 K.
const Eigen::VectorXd & m_Y_scale
Scaling factors for the species abundances, used to improve solver stability.
int df(const InputType &v_qse, JacobianType &J_qse) const
Evaluates the Jacobian of the functor, J_qse = d(f_qse)/d(v_qse).
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > JacobianType
int operator()(const InputType &v_qse, OutputType &f_qse) const
Evaluates the functor's residual vector f_qse = dY_alg/dt.
MultiscalePartitioningEngineView * m_view
Pointer to the MultiscalePartitioningEngineView instance.
bool operator<(const QSEGroup &other) const
Less-than operator for QSEGroup, used for sorting.
std::set< size_t > species_indices
Indices of all species in this group.
bool operator>(const QSEGroup &other) const
Greater-than operator for QSEGroup.
bool operator==(const QSEGroup &other) const
Equality operator for QSEGroup.
std::set< size_t > seed_indices
Indices of dynamic species in this group.
std::set< size_t > algebraic_indices
Indices of algebraic species in this group.
bool operator!=(const QSEGroup &other) const
Inequality operator for QSEGroup.
Captures the result of a network priming operation.
Definition reporting.h:67
Configuration struct for the QSE cache.
double Yi_tol
Absolute tolerance to produce the same hash for species abundances.
double rho_tol
Absolute tolerance to produce the same hash for rho.
double T9_tol
Absolute tolerance to produce the same hash for T9.
Key struct for the QSE abundance cache.
QSECacheKey(const double T9, const double rho, const std::vector< double > &Y)
Constructs a QSECacheKey.
QSECacheConfig m_cacheConfig
size_t hash() const
Computes the hash value for this key.
std::size_t m_hash
Precomputed hash value for this key.
static long bin(double value, double tol)
Converts a value to a discrete bin based on a tolerance.
bool operator==(const QSECacheKey &other) const
Equality operator for QSECacheKey.
std::vector< double > m_Y
Note that the ordering of Y must match the dynamic species indices in the view.
size_t operator()(const gridfire::QSECacheKey &key) const noexcept
Computes the hash of a QSECacheKey for use in std::unordered_map.