fix(GridFire): changes based on ref report
This commit is contained in:
@@ -70,6 +70,7 @@ struct AdaptiveEngineViewScratchPad final : AbstractScratchPad {
|
||||
/// @brief Flag indicating whether the scratchpad has been initialized.
|
||||
bool has_initialized = false;
|
||||
|
||||
|
||||
/// @brief Vector of species currently active in the adaptive network.
|
||||
std::vector<fourdst::atomic::Species> active_species;
|
||||
|
||||
|
||||
@@ -103,6 +103,9 @@ struct MultiscalePartitioningEngineViewScratchPad final : AbstractScratchPad {
|
||||
/// @brief Flag indicating whether the scratchpad has been initialized.
|
||||
bool has_initialized = false;
|
||||
|
||||
/// @breif User configurable parameter to control flux coupling threshold used
|
||||
double flux_coupling_threshold = 5.0;
|
||||
|
||||
/// @brief Vector of QSE groups representing equilibrium clusters.
|
||||
std::vector<QSEGroup> qse_groups;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "gridfire/io/generative/python.h"
|
||||
#include "gridfire/io/generative/python.h"
|
||||
#include "gridfire/io/generative/mesa.h"
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "fourdst/atomic/atomicSpecies.h"
|
||||
#include "gridfire/reaction/reaction.h"
|
||||
#include "gridfire/engine/engine_abstract.h"
|
||||
|
||||
#include <format>
|
||||
|
||||
namespace gridfire::io::generative {
|
||||
std::string get_mesa_iso_name(const fourdst::atomic::Species& species);
|
||||
|
||||
bool is_proton(const fourdst::atomic::Species& species);
|
||||
bool is_alpha(const fourdst::atomic::Species& species);
|
||||
bool is_neutron(const fourdst::atomic::Species& species);
|
||||
|
||||
std::string get_mesa_reaction_name(const reaction::Reaction& reaction);
|
||||
std::string export_engine_to_mesa_net(const engine::DynamicEngine& engine, engine::scratch::StateBlob& ctx, bool skip_weak);
|
||||
}
|
||||
|
||||
@@ -37,5 +37,5 @@ configure_file(
|
||||
output : 'config.h',
|
||||
configuration : conf_data,
|
||||
install : do_install_version_file,
|
||||
install_dir : get_option('includedir') / '/gridfire/utils'
|
||||
install_dir : get_option('includedir') / 'gridfire/utils'
|
||||
)
|
||||
@@ -1337,7 +1337,8 @@ namespace gridfire::engine {
|
||||
const double rho,
|
||||
const QSEGroup &group
|
||||
) const {
|
||||
constexpr double FLUX_RATIO_THRESHOLD = 5;
|
||||
auto* state = scratch::get_state<scratch::MultiscalePartitioningEngineViewScratchPad, true>(ctx);
|
||||
double FLUX_RATIO_THRESHOLD = state->flux_coupling_threshold;
|
||||
|
||||
const std::unordered_set<Species> algebraic_group_members(
|
||||
group.algebraic_species.begin(),
|
||||
@@ -1484,8 +1485,8 @@ namespace gridfire::engine {
|
||||
const double diff_total = std::abs(total_prod - total_dest);
|
||||
bool total_balanced = (mean_total > 0) && ((diff_total / mean_total) < 0.05);
|
||||
|
||||
// Check 2: Charged-Particle Balance (The "Neutron-Exclusion" Check)
|
||||
// Only valid if there IS charged flow (avoid 0/0 success)
|
||||
// Check 2: Charged-Particle Balance
|
||||
// Only valid if there IS charged flow
|
||||
const double mean_charged = (charged_prod + charged_dest) / 2.0;
|
||||
const double diff_charged = std::abs(charged_prod - charged_dest);
|
||||
bool charged_balanced = (mean_charged > 0) && ((diff_charged / mean_charged) < 0.05);
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "gridfire/io/generative/mesa.h"
|
||||
|
||||
#include "gridfire/engine/engine_abstract.h"
|
||||
#include "gridfire/reaction/reaction.h"
|
||||
#include "fourdst/atomic/atomicSpecies.h"
|
||||
#include "gridfire/utils/config.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cctype>
|
||||
|
||||
namespace gridfire::io::generative {
|
||||
std::string get_mesa_iso_name(const fourdst::atomic::Species& species) {
|
||||
auto name = std::string(species.name());
|
||||
std::ranges::transform(name, name.begin(), ::tolower);
|
||||
|
||||
name.erase(std::ranges::remove(name, '-').begin(), name.end());
|
||||
|
||||
if (name == "p") return "h1";
|
||||
if (name == "n" || name == "n1") return "neut";
|
||||
if (name == "d") return "h2";
|
||||
if (name == "t") return "h3";
|
||||
if (name == "a") return "he4";
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
bool is_proton(const fourdst::atomic::Species& s) { return get_mesa_iso_name(s) == "h1"; }
|
||||
bool is_alpha(const fourdst::atomic::Species& s) { return get_mesa_iso_name(s) == "he4"; }
|
||||
bool is_neutron(const fourdst::atomic::Species& s) { return get_mesa_iso_name(s) == "neut"; }
|
||||
|
||||
|
||||
std::string get_mesa_reaction_name(const reaction::Reaction& reaction) {
|
||||
std::vector<fourdst::atomic::Species> react_sorted = reaction.reactants();
|
||||
std::vector<fourdst::atomic::Species> prod_sorted = reaction.products();
|
||||
|
||||
auto sort_species = [](std::vector<fourdst::atomic::Species>& list) {
|
||||
std::ranges::sort(list, [](const auto& a, const auto& b) {
|
||||
if (a.z() != b.z()) return a.z() < b.z();
|
||||
return a.a() < b.a();
|
||||
});
|
||||
};
|
||||
|
||||
sort_species(react_sorted);
|
||||
sort_species(prod_sorted);
|
||||
|
||||
if (react_sorted.size() == 1 && prod_sorted.size() == 1) {
|
||||
if (reaction.type() == reaction::ReactionType::WEAK ||
|
||||
reaction.type() == reaction::ReactionType::REACLIB_WEAK ||
|
||||
reaction.type() == reaction::ReactionType::LOGICAL_REACLIB_WEAK) {
|
||||
return "r_" + get_mesa_iso_name(react_sorted[0]) + "_wk_" + get_mesa_iso_name(prod_sorted[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (react_sorted.size() == 2 && prod_sorted.size() == 1) {
|
||||
std::string x, cap;
|
||||
if (is_proton(react_sorted[0]) || is_proton(react_sorted[1])) {
|
||||
cap = "pg";
|
||||
x = is_proton(react_sorted[0]) ? get_mesa_iso_name(react_sorted[1]) : get_mesa_iso_name(react_sorted[0]);
|
||||
}
|
||||
else if (is_alpha(react_sorted[0]) || is_alpha(react_sorted[1])) {
|
||||
cap = "ag";
|
||||
x = is_alpha(react_sorted[0]) ? get_mesa_iso_name(react_sorted[1]) : get_mesa_iso_name(react_sorted[0]);
|
||||
}
|
||||
else if (is_neutron(react_sorted[0]) || is_neutron(react_sorted[1])) {
|
||||
cap = "ng";
|
||||
x = is_neutron(react_sorted[0]) ? get_mesa_iso_name(react_sorted[1]) : get_mesa_iso_name(react_sorted[0]);
|
||||
}
|
||||
|
||||
if (!cap.empty()) return "r_" + x + "_" + cap + "_" + get_mesa_iso_name(prod_sorted[0]);
|
||||
}
|
||||
|
||||
if (react_sorted.size() == 1 && prod_sorted.size() == 2) {
|
||||
std::string x, em;
|
||||
if (is_proton(prod_sorted[0]) || is_proton(prod_sorted[1])) {
|
||||
em = "gp";
|
||||
x = is_proton(prod_sorted[0]) ? get_mesa_iso_name(prod_sorted[1]) : get_mesa_iso_name(prod_sorted[0]);
|
||||
}
|
||||
else if (is_alpha(prod_sorted[0]) || is_alpha(prod_sorted[1])) {
|
||||
em = "ga";
|
||||
x = is_alpha(prod_sorted[0]) ? get_mesa_iso_name(prod_sorted[1]) : get_mesa_iso_name(prod_sorted[0]);
|
||||
}
|
||||
else if (is_neutron(prod_sorted[0]) || is_neutron(prod_sorted[1])) {
|
||||
em = "gn";
|
||||
x = is_neutron(prod_sorted[0]) ? get_mesa_iso_name(prod_sorted[1]) : get_mesa_iso_name(prod_sorted[0]);
|
||||
}
|
||||
|
||||
if (!em.empty()) return "r_" + get_mesa_iso_name(react_sorted[0]) + "_" + em + "_" + x;
|
||||
}
|
||||
|
||||
if (react_sorted.size() == 2 && prod_sorted.size() == 2) {
|
||||
int r_p = -1, r_a = -1, r_n = -1;
|
||||
int p_p = -1, p_a = -1, p_n = -1;
|
||||
|
||||
for(int i=0; i<2; ++i) {
|
||||
if(is_proton(react_sorted[i])) r_p = i;
|
||||
if(is_alpha(react_sorted[i])) r_a = i;
|
||||
if(is_neutron(react_sorted[i])) r_n = i;
|
||||
|
||||
if(is_proton(prod_sorted[i])) p_p = i;
|
||||
if(is_alpha(prod_sorted[i])) p_a = i;
|
||||
if(is_neutron(prod_sorted[i])) p_n = i;
|
||||
}
|
||||
|
||||
std::string x, y, exc;
|
||||
if (r_a != -1 && p_p != -1) { exc = "ap"; x = get_mesa_iso_name(react_sorted[1-r_a]); y = get_mesa_iso_name(prod_sorted[1-p_p]); }
|
||||
else if (r_p != -1 && p_a != -1) { exc = "pa"; x = get_mesa_iso_name(react_sorted[1-r_p]); y = get_mesa_iso_name(prod_sorted[1-p_a]); }
|
||||
else if (r_n != -1 && p_p != -1) { exc = "np"; x = get_mesa_iso_name(react_sorted[1-r_n]); y = get_mesa_iso_name(prod_sorted[1-p_p]); }
|
||||
else if (r_p != -1 && p_n != -1) { exc = "pn"; x = get_mesa_iso_name(react_sorted[1-r_p]); y = get_mesa_iso_name(prod_sorted[1-p_n]); }
|
||||
else if (r_n != -1 && p_a != -1) { exc = "na"; x = get_mesa_iso_name(react_sorted[1-r_n]); y = get_mesa_iso_name(prod_sorted[1-p_a]); }
|
||||
else if (r_a != -1 && p_n != -1) { exc = "an"; x = get_mesa_iso_name(react_sorted[1-r_a]); y = get_mesa_iso_name(prod_sorted[1-p_n]); }
|
||||
|
||||
if (!exc.empty()) return "r_" + x + "_" + exc + "_" + y;
|
||||
}
|
||||
|
||||
std::string fallback = "r";
|
||||
for (const auto& s : react_sorted) fallback += "_" + get_mesa_iso_name(s);
|
||||
fallback += "_to";
|
||||
for (const auto& s : prod_sorted) fallback += "_" + get_mesa_iso_name(s);
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
std::string export_engine_to_mesa_net(const engine::DynamicEngine& engine, engine::scratch::StateBlob& ctx, bool skip_weak) {
|
||||
std::stringstream ss;
|
||||
ss << "! Auto-generated MESA .net file from GridFire\n";
|
||||
ss << "! Generated by GridFire version: " << version().toString() << "\n";
|
||||
ss << "! Generated on " << std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) << "\n\n";
|
||||
|
||||
ss << "add_isos(\n";
|
||||
for (const auto& species : engine.getNetworkSpecies(ctx)) {
|
||||
ss << " " << get_mesa_iso_name(species) << "\n";
|
||||
}
|
||||
ss << ")\n\n";
|
||||
|
||||
ss << "add_reactions(\n";
|
||||
const auto& reactions = engine.getNetworkReactions(ctx);
|
||||
|
||||
for (const auto& reaction_ptr : reactions) {
|
||||
if (skip_weak && (reaction_ptr->type() == reaction::ReactionType::WEAK ||
|
||||
reaction_ptr->type() == reaction::ReactionType::REACLIB_WEAK ||
|
||||
reaction_ptr->type() == reaction::ReactionType::LOGICAL_REACLIB_WEAK)) {
|
||||
continue;
|
||||
}
|
||||
ss << " " << get_mesa_reaction_name(*reaction_ptr) << "\n";
|
||||
}
|
||||
ss << ")\n";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,14 +61,7 @@ namespace gridfire::policy {
|
||||
std::make_unique<engine::GraphEngine>(m_initializing_composition, *m_partition_function, engine::NetworkBuildDepth::ThirdOrder, engine::NetworkConstructionFlags::DEFAULT)
|
||||
);
|
||||
|
||||
m_network_stack.emplace_back(
|
||||
std::make_unique<engine::MultiscalePartitioningEngineView>(*m_network_stack.back().get())
|
||||
);
|
||||
m_network_stack.emplace_back(
|
||||
std::make_unique<engine::AdaptiveEngineView>(*m_network_stack.back().get())
|
||||
);
|
||||
|
||||
std::unique_ptr<engine::scratch::StateBlob> scratch_blob = get_stack_scratch_blob();
|
||||
std::unique_ptr<engine::scratch::StateBlob> scratch_blob = m_network_stack.back()->constructStateBlob(nullptr);
|
||||
m_status = NetworkPolicyStatus::INITIALIZED_UNVERIFIED;
|
||||
m_status = check_status(*scratch_blob);
|
||||
|
||||
@@ -110,8 +103,6 @@ namespace gridfire::policy {
|
||||
std::vector<engine::EngineTypes> MainSequencePolicy::get_engine_types_stack() const {
|
||||
return {
|
||||
engine::EngineTypes::GRAPH_ENGINE,
|
||||
engine::EngineTypes::MULTISCALE_PARTITIONING_ENGINE_VIEW,
|
||||
engine::EngineTypes::ADAPTIVE_ENGINE_VIEW
|
||||
};
|
||||
}
|
||||
|
||||
@@ -125,32 +116,14 @@ namespace gridfire::policy {
|
||||
}
|
||||
auto blob = std::make_unique<engine::scratch::StateBlob>();
|
||||
blob->enroll<engine::scratch::GraphEngineScratchPad>();
|
||||
blob->enroll<engine::scratch::AdaptiveEngineViewScratchPad>();
|
||||
blob->enroll<engine::scratch::MultiscalePartitioningEngineViewScratchPad>();
|
||||
|
||||
|
||||
const engine::GraphEngine* graph_engine = dynamic_cast<engine::GraphEngine*>(m_network_stack.front().get());
|
||||
if (!graph_engine) {
|
||||
throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The base engine is not a GraphEngine. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you.");
|
||||
}
|
||||
|
||||
const engine::MultiscalePartitioningEngineView* multiscale_engine = dynamic_cast<engine::MultiscalePartitioningEngineView*>(m_network_stack[1].get());
|
||||
if (!multiscale_engine) {
|
||||
throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The middle engine is not a MultiscalePartitioningEngineView. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you.");
|
||||
}
|
||||
|
||||
const engine::AdaptiveEngineView* adaptive_engine = dynamic_cast<engine::AdaptiveEngineView*>(m_network_stack.back().get());
|
||||
if (!adaptive_engine) {
|
||||
throw exceptions::PolicyError("Cannot get stack scratch blob from MainSequencePolicy: The top engine is not an AdaptiveEngineView. This indicates a serious internal inconsistency and should be reported to the GridFire developers, thank you.");
|
||||
}
|
||||
|
||||
|
||||
auto* graph_engine_state = engine::scratch::get_state<engine::scratch::GraphEngineScratchPad, false>(*blob);
|
||||
graph_engine_state->initialize(*graph_engine);
|
||||
auto* multiscale_engine_state = engine::scratch::get_state<engine::scratch::MultiscalePartitioningEngineViewScratchPad, false>(*blob);
|
||||
multiscale_engine_state->initialize();
|
||||
auto* adaptive_engine_state = engine::scratch::get_state<engine::scratch::AdaptiveEngineViewScratchPad, false>(*blob);
|
||||
adaptive_engine_state->initialize(*adaptive_engine);
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ gridfire_sources = files(
|
||||
'lib/reaction/weak/weak_interpolator.cpp',
|
||||
'lib/io/network_file.cpp',
|
||||
'lib/io/generative/python.cpp',
|
||||
'lib/io/generative/mesa.cpp',
|
||||
'lib/solver/strategies/PointSolver.cpp',
|
||||
'lib/solver/strategies/GridSolver.cpp',
|
||||
'lib/solver/strategies/triggers/engine_partitioning_trigger.cpp',
|
||||
|
||||
Reference in New Issue
Block a user