fix(MultiscalePartitioningEngineView): made qse partitioning much more robust
This commit is contained in:
@@ -4,11 +4,11 @@
|
||||
#include "gridfire/engine/views/engine_view_abstract.h"
|
||||
#include "gridfire/engine/engine_graph.h"
|
||||
|
||||
#include "Eigen/Dense"
|
||||
#include "unsupported/Eigen/NonLinearOptimization"
|
||||
|
||||
namespace gridfire {
|
||||
class MultiscalePartitioningEngineView final: public DynamicEngine, public EngineView<DynamicEngine> {
|
||||
typedef std::tuple<std::vector<fourdst::atomic::Species>, std::vector<size_t>, std::vector<fourdst::atomic::Species>, std::vector<size_t>> QSEPartition;
|
||||
public:
|
||||
explicit MultiscalePartitioningEngineView(GraphEngine& baseEngine);
|
||||
|
||||
@@ -68,16 +68,19 @@ namespace gridfire {
|
||||
void partitionNetwork(
|
||||
const std::vector<double>& Y,
|
||||
double T9,
|
||||
double rho,
|
||||
double dt_control
|
||||
double rho
|
||||
);
|
||||
|
||||
void partitionNetwork(
|
||||
const NetIn& netIn,
|
||||
double dt_control
|
||||
const NetIn& netIn
|
||||
);
|
||||
|
||||
void exportToDot(const std::string& filename) const;
|
||||
void exportToDot(
|
||||
const std::string& filename,
|
||||
const std::vector<double>& Y,
|
||||
const double T9,
|
||||
const double rho
|
||||
) const;
|
||||
|
||||
[[nodiscard]] int getSpeciesIndex(const fourdst::atomic::Species &species) const override;
|
||||
|
||||
@@ -91,21 +94,53 @@ namespace gridfire {
|
||||
fourdst::composition::Composition equilibrateNetwork(
|
||||
const std::vector<double> &Y,
|
||||
double T9,
|
||||
double rho,
|
||||
double dt_control
|
||||
double rho
|
||||
);
|
||||
|
||||
fourdst::composition::Composition equilibrateNetwork(
|
||||
const NetIn &netIn,
|
||||
const double dt_control
|
||||
const NetIn &netIn
|
||||
);
|
||||
|
||||
|
||||
private:
|
||||
struct QSEGroup {
|
||||
std::vector<size_t> species_indices; ///< Indices of all species in this group.
|
||||
size_t seed_nucleus_index; ///< Index of the one species that will be evolved dynamically.
|
||||
std::set<size_t> species_indices; ///< Indices of all species in this group.
|
||||
bool is_in_equilibrium = false; ///< Flag set by flux analysis.
|
||||
std::set<size_t> algebraic_indices; ///< Indices of algebraic species in this group.
|
||||
std::set<size_t> seed_indices; ///< Indices of dynamic species in this group.
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const QSEGroup& group) {
|
||||
os << "QSEGroup(species_indices: [";
|
||||
int count = 0;
|
||||
for (const auto& idx : group.species_indices) {
|
||||
os << idx;
|
||||
if (count < group.species_indices.size() - 1) {
|
||||
os << ", ";
|
||||
}
|
||||
count++;
|
||||
}
|
||||
count = 0;
|
||||
os << "], is_in_equilibrium: " << group.is_in_equilibrium
|
||||
<< ", algebraic_indices: [";
|
||||
for (const auto& idx : group.algebraic_indices) {
|
||||
os << idx;
|
||||
if (count < group.algebraic_indices.size() - 1) {
|
||||
os << ", ";
|
||||
}
|
||||
count++;
|
||||
}
|
||||
count = 0;
|
||||
os << "], seed_indices: [";
|
||||
for (const auto& idx : group.seed_indices) {
|
||||
os << idx;
|
||||
if (count < group.seed_indices.size() - 1) {
|
||||
os << ", ";
|
||||
}
|
||||
count++;
|
||||
}
|
||||
os << "])";
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
struct EigenFunctor {
|
||||
@@ -147,36 +182,29 @@ namespace gridfire {
|
||||
};
|
||||
|
||||
private:
|
||||
quill::Logger* m_logger = fourdst::logging::LogManager::getInstance().getLogger("log");
|
||||
quill::Logger* m_logger = LogManager::getInstance().getLogger("log");
|
||||
GraphEngine& m_baseEngine; ///< The base engine to which this view delegates calculations.
|
||||
std::vector<QSEGroup> m_qse_groups; ///< The list of identified equilibrium groups.
|
||||
std::vector<fourdst::atomic::Species> m_dynamic_species; ///< The simplified set of species presented to the solver.
|
||||
std::vector<size_t> m_dynamic_species_indices; ///< Indices mapping the dynamic species back to the master engine's list.
|
||||
std::vector<fourdst::atomic::Species> m_algebraic_species; ///< Species that are algebraic in the QSE groups.
|
||||
std::vector<size_t> m_algebraic_species_indices; ///< Indices of algebraic species in the full network.
|
||||
std::unordered_map<size_t, std::vector<size_t>> m_connectivity_graph;
|
||||
|
||||
private:
|
||||
std::unordered_set<size_t> identifyFastReactions(
|
||||
const std::vector<double>& Y_full,
|
||||
double T9,
|
||||
double rho,
|
||||
double dt_control
|
||||
) const;
|
||||
|
||||
void buildConnectivityGraph(
|
||||
const std::unordered_set<size_t>& fast_reaction_indices
|
||||
);
|
||||
|
||||
void findConnectedComponents();
|
||||
|
||||
void validateGroupsWithFluxAnalysis(
|
||||
const std::vector<double>& Y,
|
||||
std::vector<std::vector<size_t>> partitionByTimescale(
|
||||
const std::vector<double> &Y_full,
|
||||
double T9,
|
||||
double rho
|
||||
);
|
||||
) const;
|
||||
|
||||
std::pair<std::vector<fourdst::atomic::Species>, std::vector<size_t>> identifyDynamicSpecies(
|
||||
std::unordered_map<size_t, std::vector<size_t>> buildConnectivityGraph(
|
||||
const std::unordered_set<size_t> &fast_reaction_indices
|
||||
) const;
|
||||
|
||||
std::vector<QSEGroup> validateGroupsWithFluxAnalysis(
|
||||
const std::vector<QSEGroup> &candidate_groups,
|
||||
const std::vector<double>& Y,
|
||||
const std::vector<QSEGroup>& qse_groups,
|
||||
double T9,
|
||||
double rho
|
||||
) const;
|
||||
@@ -186,5 +214,19 @@ namespace gridfire {
|
||||
double T9,
|
||||
double rho
|
||||
);
|
||||
|
||||
size_t identifyMeanSlowestPool(
|
||||
const std::vector<std::vector<size_t>>& pools,
|
||||
const std::vector<double> &Y,
|
||||
double T9,
|
||||
double rho
|
||||
) const;
|
||||
|
||||
std::vector<QSEGroup> constructCandidateGroups(
|
||||
const std::vector<std::vector<size_t>>& timescale_pools,
|
||||
const std::vector<double>& Y,
|
||||
double T9,
|
||||
double rho
|
||||
) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -690,23 +690,23 @@ namespace gridfire {
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEBUG(
|
||||
m_logger,
|
||||
"Final Jacobian is:\n{}",
|
||||
[&]() -> std::string {
|
||||
std::stringstream ss;
|
||||
ss << std::scientific << std::setprecision(5);
|
||||
for (size_t i = 0; i < m_jacobianMatrix.size1(); ++i) {
|
||||
for (size_t j = 0; j < m_jacobianMatrix.size2(); ++j) {
|
||||
ss << m_jacobianMatrix(i, j);
|
||||
if (j < m_jacobianMatrix.size2() - 1) {
|
||||
ss << ", ";
|
||||
}
|
||||
}
|
||||
ss << "\n";
|
||||
}
|
||||
return ss.str();
|
||||
}());
|
||||
// LOG_DEBUG(
|
||||
// m_logger,
|
||||
// "Final Jacobian is:\n{}",
|
||||
// [&]() -> std::string {
|
||||
// std::stringstream ss;
|
||||
// ss << std::scientific << std::setprecision(5);
|
||||
// for (size_t i = 0; i < m_jacobianMatrix.size1(); ++i) {
|
||||
// for (size_t j = 0; j < m_jacobianMatrix.size2(); ++j) {
|
||||
// ss << m_jacobianMatrix(i, j);
|
||||
// if (j < m_jacobianMatrix.size2() - 1) {
|
||||
// ss << ", ";
|
||||
// }
|
||||
// }
|
||||
// ss << "\n";
|
||||
// }
|
||||
// return ss.str();
|
||||
// }());
|
||||
LOG_TRACE_L1(m_logger, "Jacobian matrix generated with dimensions: {} rows x {} columns.", m_jacobianMatrix.size1(), m_jacobianMatrix.size2());
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,10 @@ namespace gridfire {
|
||||
if (destructionRateConstant > 1e-99) {
|
||||
const double creationRate = calculateCreationRate(primer, primingSpecies, Y, T9, rho);
|
||||
equilibriumMassFraction = (creationRate / destructionRateConstant) * primingSpecies.mass();
|
||||
if (std::isnan(equilibriumMassFraction)) {
|
||||
LOG_WARNING(logger, "Equilibrium mass fraction for {} is NaN. Setting to 0.0. This is likely not an issue. It probably originates from all reactions leading to creation and destruction being frozen out. In that case 0.0 should be a good approximation. Hint: This happens often when the network temperature is very the low. ", primingSpecies.name());
|
||||
equilibriumMassFraction = 0.0;
|
||||
}
|
||||
LOG_INFO(logger, "Found equilibrium for {}: X_eq = {:.4e}", primingSpecies.name(), equilibriumMassFraction);
|
||||
|
||||
const reaction::Reaction* dominantChannel = findDominantCreationChannel(primer, primingSpecies, Y, T9, rho);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user