feat(GraphEngine): More robust reaction type selection at network construction
Added new ways to select exactly what types of reactions (strong, beta+, beta-, electron capture, positron capture, or any combination thereof) can be turned on at network construction time. There are a few quality of life masks added as well such as weak which addes all weak type reactions, and all which adds weak + strong reactions. The default is to just add strong reactions for now.
This commit is contained in:
@@ -1,33 +1,35 @@
|
||||
# --- Python Extension Setup ---
|
||||
py_installation = import('python').find_installation('python3')
|
||||
|
||||
gridfire_py_deps = [
|
||||
pybind11_dep,
|
||||
const_dep,
|
||||
config_dep,
|
||||
composition_dep,
|
||||
gridfire_dep
|
||||
]
|
||||
|
||||
py_mod = py_installation.extension_module(
|
||||
'gridfire', # Name of the generated .so/.pyd file (without extension)
|
||||
sources: [
|
||||
meson.project_source_root() + '/src/python/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/types/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/expectations/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/partition/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/partition/trampoline/py_partition.cpp',
|
||||
meson.project_source_root() + '/src/python/reaction/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/screening/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/screening/trampoline/py_screening.cpp',
|
||||
meson.project_source_root() + '/src/python/io/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/io/trampoline/py_io.cpp',
|
||||
meson.project_source_root() + '/src/python/exceptions/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/engine/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/engine/trampoline/py_engine.cpp',
|
||||
meson.project_source_root() + '/src/python/solver/bindings.cpp',
|
||||
meson.project_source_root() + '/src/python/solver/trampoline/py_solver.cpp',
|
||||
meson.project_source_root() + '/src/python/utils/bindings.cpp',
|
||||
],
|
||||
dependencies : [
|
||||
pybind11_dep,
|
||||
const_dep,
|
||||
config_dep,
|
||||
composition_dep,
|
||||
gridfire_dep,
|
||||
# meson.project_source_root() + '/src/python/expectations/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/partition/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/partition/trampoline/py_partition.cpp',
|
||||
# meson.project_source_root() + '/src/python/reaction/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/screening/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/screening/trampoline/py_screening.cpp',
|
||||
# meson.project_source_root() + '/src/python/io/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/io/trampoline/py_io.cpp',
|
||||
# meson.project_source_root() + '/src/python/exceptions/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/engine/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/engine/trampoline/py_engine.cpp',
|
||||
# meson.project_source_root() + '/src/python/solver/bindings.cpp',
|
||||
# meson.project_source_root() + '/src/python/solver/trampoline/py_solver.cpp',
|
||||
# meson.project_source_root() + '/src/python/utils/bindings.cpp',
|
||||
],
|
||||
dependencies : gridfire_py_deps,
|
||||
cpp_args : ['-UNDEBUG'], # Example: Ensure assertions are enabled if needed
|
||||
install : true,
|
||||
)
|
||||
@@ -119,6 +119,13 @@ namespace gridfire {
|
||||
BuildDepthType buildDepth = NetworkBuildDepth::Full
|
||||
);
|
||||
|
||||
explicit GraphEngine(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const partition::PartitionFunction& partitionFunction,
|
||||
BuildDepthType buildDepth,
|
||||
NetworkConstructionFlags reactionTypes
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Constructs a GraphEngine from a set of reactions.
|
||||
*
|
||||
|
||||
@@ -11,6 +11,76 @@
|
||||
|
||||
namespace gridfire {
|
||||
|
||||
|
||||
enum class NetworkConstructionFlags : uint32_t {
|
||||
NONE = 0,
|
||||
|
||||
STRONG = 1 << 0, // 1
|
||||
|
||||
BETA_MINUS = 1 << 1, // 2
|
||||
BETA_PLUS = 1 << 2, // 4
|
||||
ELECTRON_CAPTURE = 1 << 3, // 8
|
||||
POSITRON_CAPTURE = 1 << 4, // 16
|
||||
|
||||
WEAK = BETA_MINUS | BETA_PLUS | ELECTRON_CAPTURE | POSITRON_CAPTURE,
|
||||
DEFAULT = STRONG,
|
||||
ALL = STRONG | WEAK
|
||||
};
|
||||
|
||||
constexpr auto to_underlying(NetworkConstructionFlags f) noexcept {
|
||||
return static_cast<std::underlying_type_t<NetworkConstructionFlags>>(f);
|
||||
}
|
||||
|
||||
inline NetworkConstructionFlags operator|(const NetworkConstructionFlags lhs, const NetworkConstructionFlags rhs) {
|
||||
return static_cast<NetworkConstructionFlags>(to_underlying(lhs) | to_underlying(rhs));
|
||||
}
|
||||
|
||||
inline NetworkConstructionFlags operator&(const NetworkConstructionFlags lhs, const NetworkConstructionFlags rhs) {
|
||||
return static_cast<NetworkConstructionFlags>(to_underlying(lhs) & to_underlying(rhs));
|
||||
}
|
||||
|
||||
inline bool has_flag(const NetworkConstructionFlags flags, const NetworkConstructionFlags flag_to_check) {
|
||||
return (flags & flag_to_check) != NetworkConstructionFlags::NONE;
|
||||
}
|
||||
|
||||
inline std::string NetworkConstructionFlagsToString(NetworkConstructionFlags flags) {
|
||||
std::stringstream ss;
|
||||
constexpr std::array<NetworkConstructionFlags, 5> bases_flags_array = {
|
||||
NetworkConstructionFlags::STRONG,
|
||||
NetworkConstructionFlags::BETA_MINUS,
|
||||
NetworkConstructionFlags::BETA_PLUS,
|
||||
NetworkConstructionFlags::ELECTRON_CAPTURE,
|
||||
NetworkConstructionFlags::POSITRON_CAPTURE
|
||||
};
|
||||
|
||||
const std::unordered_map<NetworkConstructionFlags, std::string> bases_string_map = {
|
||||
{NetworkConstructionFlags::STRONG, "Strong"},
|
||||
{NetworkConstructionFlags::BETA_MINUS, "BetaMinus"},
|
||||
{NetworkConstructionFlags::BETA_PLUS, "BetaPlus"},
|
||||
{NetworkConstructionFlags::ELECTRON_CAPTURE, "ElectronCapture"},
|
||||
{NetworkConstructionFlags::POSITRON_CAPTURE, "PositronCapture"}
|
||||
};
|
||||
|
||||
size_t i = 0;
|
||||
for (const auto& flagType : bases_flags_array) {
|
||||
if (has_flag(flags, flagType)) {
|
||||
ss << bases_string_map.at(flagType);
|
||||
if (i < bases_flags_array.size() - 1) {
|
||||
ss << ", ";
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
std::string result = ss.str();
|
||||
if (result.empty()) {
|
||||
return "No reactions";
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Builds a nuclear reaction network from the Reaclib library based on an initial composition.
|
||||
*
|
||||
@@ -26,7 +96,7 @@ namespace gridfire {
|
||||
* @param weakInterpolator Interpolator to build weak rates from. Must be constructed and owned by the caller.
|
||||
* @param maxLayers Variant specifying either a predefined NetworkBuildDepth or a custom integer depth;
|
||||
* negative depth (Full) collects all reactions, zero is invalid.
|
||||
* @param reverse If true, collects reverse reactions (decays or back-reactions); if false, uses forward reactions.
|
||||
* @param ReactionTypes
|
||||
* @pre composition must have at least one species with positive mass fraction.
|
||||
* @pre Resolved integer depth from maxLayers must not be zero.
|
||||
* @post Returned network includes only reactions satisfying the depth and reverse criteria.
|
||||
@@ -35,8 +105,8 @@ namespace gridfire {
|
||||
*/
|
||||
reaction::ReactionSet build_nuclear_network(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const rates::weak::WeakRateInterpolator &weakInterpolator,
|
||||
const std::optional<rates::weak::WeakRateInterpolator> &weakInterpolator,
|
||||
BuildDepthType maxLayers = NetworkBuildDepth::Full,
|
||||
bool reverse = false
|
||||
NetworkConstructionFlags ReactionTypes = NetworkConstructionFlags::DEFAULT
|
||||
);
|
||||
}
|
||||
|
||||
@@ -779,6 +779,8 @@ namespace gridfire::reaction {
|
||||
|
||||
void add_reaction(std::unique_ptr<Reaction>&& reaction);
|
||||
|
||||
void extend(const ReactionSet& other);
|
||||
|
||||
/**
|
||||
* @brief Removes a reaction from the set.
|
||||
* @param reaction The Reaction to remove.
|
||||
|
||||
@@ -40,9 +40,16 @@ namespace gridfire {
|
||||
GraphEngine::GraphEngine(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const partition::PartitionFunction& partitionFunction,
|
||||
const BuildDepthType buildDepth) :
|
||||
const BuildDepthType buildDepth
|
||||
) : GraphEngine(composition, partitionFunction, buildDepth, NetworkConstructionFlags::DEFAULT){}
|
||||
|
||||
GraphEngine::GraphEngine(
|
||||
const fourdst::composition::Composition &composition,
|
||||
const partition::PartitionFunction &partitionFunction,
|
||||
const BuildDepthType buildDepth,
|
||||
const NetworkConstructionFlags reactionTypes ) :
|
||||
m_weakRateInterpolator(rates::weak::UNIFIED_WEAK_DATA),
|
||||
m_reactions(build_nuclear_network(composition, m_weakRateInterpolator, buildDepth, false)),
|
||||
m_reactions(build_nuclear_network(composition, m_weakRateInterpolator, buildDepth, reactionTypes)),
|
||||
m_depth(buildDepth),
|
||||
m_partitionFunction(partitionFunction.clone())
|
||||
{
|
||||
@@ -576,7 +583,7 @@ namespace gridfire {
|
||||
void GraphEngine::rebuild(const fourdst::composition::Composition& comp, const BuildDepthType depth) {
|
||||
if (depth != m_depth) {
|
||||
m_depth = depth;
|
||||
m_reactions = build_nuclear_network(comp, m_weakRateInterpolator, m_depth, false);
|
||||
m_reactions = build_nuclear_network(comp, m_weakRateInterpolator, m_depth);
|
||||
m_jacobianMatrixState = JacobianMatrixState::STALE;
|
||||
syncInternalMaps(); // Resync internal maps after changing the depth
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,86 @@ namespace {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
gridfire::reaction::ReactionSet register_weak_reactions(
|
||||
const std::optional<gridfire::rates::weak::WeakRateInterpolator> &weakInterpolator,
|
||||
const gridfire::NetworkConstructionFlags reactionTypes
|
||||
) {
|
||||
gridfire::reaction::ReactionSet weak_reaction_pool;
|
||||
assert(weakInterpolator.has_value());
|
||||
if (!has_flag(reactionTypes, gridfire::NetworkConstructionFlags::WEAK)) {
|
||||
return weak_reaction_pool;
|
||||
}
|
||||
|
||||
for (const auto& parent_species: weakInterpolator->available_isotopes()) {
|
||||
std::expected<fourdst::atomic::Species, fourdst::atomic::SpeciesErrorType> upProduct = fourdst::atomic::az_to_species(
|
||||
parent_species.a(),
|
||||
parent_species.z() + 1
|
||||
);
|
||||
std::expected<fourdst::atomic::Species, fourdst::atomic::SpeciesErrorType> downProduct = fourdst::atomic::az_to_species(
|
||||
parent_species.a(),
|
||||
parent_species.z() - 1
|
||||
);
|
||||
if (downProduct.has_value()) { // Only add the reaction if the Species map contains the product
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::BETA_PLUS)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
gridfire::rates::weak::WeakReactionType::BETA_PLUS_DECAY,
|
||||
*weakInterpolator
|
||||
)
|
||||
);
|
||||
}
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::ELECTRON_CAPTURE)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
gridfire::rates::weak::WeakReactionType::ELECTRON_CAPTURE,
|
||||
*weakInterpolator
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (upProduct.has_value()) { // Only add the reaction if the Species map contains the product
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::BETA_MINUS)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
gridfire::rates::weak::WeakReactionType::BETA_MINUS_DECAY,
|
||||
*weakInterpolator
|
||||
)
|
||||
);
|
||||
}
|
||||
if (has_flag(reactionTypes, gridfire::NetworkConstructionFlags::POSITRON_CAPTURE)) {
|
||||
weak_reaction_pool.add_reaction(
|
||||
std::make_unique<gridfire::rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
gridfire::rates::weak::WeakReactionType::POSITRON_CAPTURE,
|
||||
*weakInterpolator
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return weak_reaction_pool;
|
||||
}
|
||||
|
||||
gridfire::reaction::ReactionSet register_strong_reactions(
|
||||
const gridfire::NetworkConstructionFlags reaction_types
|
||||
) {
|
||||
gridfire::reaction::ReactionSet strong_reaction_pool;
|
||||
if (has_flag(reaction_types, gridfire::NetworkConstructionFlags::STRONG)) {
|
||||
const auto& allReaclibReactions = gridfire::reaclib::get_all_reaclib_reactions();
|
||||
for (const auto& reaction : allReaclibReactions) {
|
||||
if (!reaction->is_reverse() && !reaclib_reaction_is_weak(*reaction)) { // Only add reactions of the correct direction and which are not weak. Weak reactions are handled from the WRL separately which provides much higher quality weak reactions than reaclib does
|
||||
strong_reaction_pool.add_reaction(reaction->clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
return strong_reaction_pool;
|
||||
}
|
||||
}
|
||||
|
||||
namespace gridfire {
|
||||
@@ -45,20 +125,26 @@ namespace gridfire {
|
||||
using fourdst::composition::Composition;
|
||||
using fourdst::atomic::Species;
|
||||
|
||||
|
||||
ReactionSet build_nuclear_network(
|
||||
const Composition& composition,
|
||||
const rates::weak::WeakRateInterpolator& weakInterpolator,
|
||||
const std::optional<rates::weak::WeakRateInterpolator> &weakInterpolator,
|
||||
BuildDepthType maxLayers,
|
||||
bool reverse
|
||||
NetworkConstructionFlags ReactionTypes
|
||||
) {
|
||||
auto logger = fourdst::logging::LogManager::getInstance().getLogger("log");
|
||||
LOG_INFO(logger, "Constructing network topology from reaction types : {}", NetworkConstructionFlagsToString(ReactionTypes));
|
||||
|
||||
if (ReactionTypes == NetworkConstructionFlags::NONE) {
|
||||
LOG_ERROR(logger, "Reaction types is set to NONE. No reactions will be collected");
|
||||
throw std::logic_error("Reaction types is set to NONE. No reactions will be collected");
|
||||
}
|
||||
|
||||
int depth;
|
||||
if (std::holds_alternative<NetworkBuildDepth>(maxLayers)) {
|
||||
depth = static_cast<int>(std::get<NetworkBuildDepth>(maxLayers));
|
||||
} else {
|
||||
depth = std::get<int>(maxLayers);
|
||||
}
|
||||
auto logger = fourdst::logging::LogManager::getInstance().getLogger("log");
|
||||
if (depth == 0) {
|
||||
LOG_ERROR(logger, "Network build depth is set to 0. No reactions will be collected.");
|
||||
throw std::logic_error("Network build depth is set to 0. No reactions will be collected.");
|
||||
@@ -68,56 +154,10 @@ namespace gridfire {
|
||||
ReactionSet master_reaction_pool;
|
||||
|
||||
// Clone all relevant REACLIB reactions into the master pool
|
||||
const auto& allReaclibReactions = reaclib::get_all_reaclib_reactions();
|
||||
for (const auto& reaction : allReaclibReactions) {
|
||||
if (reaction->is_reverse() == reverse && !reaclib_reaction_is_weak(*reaction)) { // Only add reactions of the correct direction and which are not weak. Weak reactions are handled from the WRL separately which provides much higher quality weak reactions than reaclib does
|
||||
master_reaction_pool.add_reaction(reaction->clone());
|
||||
}
|
||||
}
|
||||
master_reaction_pool.extend(register_strong_reactions(ReactionTypes));
|
||||
|
||||
// --- Clone all possible weak reactions into the master reaction pool ---
|
||||
for (const auto& parent_species: weakInterpolator.available_isotopes()) {
|
||||
std::expected<Species, fourdst::atomic::SpeciesErrorType> upProduct = fourdst::atomic::az_to_species(
|
||||
parent_species.a(),
|
||||
parent_species.z() + 1
|
||||
);
|
||||
std::expected<Species, fourdst::atomic::SpeciesErrorType> downProduct = fourdst::atomic::az_to_species(
|
||||
parent_species.a(),
|
||||
parent_species.z() - 1
|
||||
);
|
||||
if (downProduct.has_value()) { // Only add the reaction if the Species map contains the product
|
||||
master_reaction_pool.add_reaction(
|
||||
std::make_unique<rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
rates::weak::WeakReactionType::BETA_PLUS_DECAY,
|
||||
weakInterpolator
|
||||
)
|
||||
);
|
||||
master_reaction_pool.add_reaction(
|
||||
std::make_unique<rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
rates::weak::WeakReactionType::ELECTRON_CAPTURE,
|
||||
weakInterpolator
|
||||
)
|
||||
);
|
||||
}
|
||||
if (upProduct.has_value()) { // Only add the reaction if the Species map contains the product
|
||||
master_reaction_pool.add_reaction(
|
||||
std::make_unique<rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
rates::weak::WeakReactionType::BETA_MINUS_DECAY,
|
||||
weakInterpolator
|
||||
)
|
||||
);
|
||||
master_reaction_pool.add_reaction(
|
||||
std::make_unique<rates::weak::WeakReaction>(
|
||||
parent_species,
|
||||
rates::weak::WeakReactionType::POSITRON_CAPTURE,
|
||||
weakInterpolator
|
||||
)
|
||||
);
|
||||
}
|
||||
} // TODO: Remove comments, weak reactions have been disabled for testing
|
||||
// --- Clone all possible weak reactions into the master reaction pool if the construction function is told to use weak reactions ---
|
||||
master_reaction_pool.extend(register_weak_reactions(weakInterpolator, ReactionTypes));
|
||||
|
||||
// --- Step 2: Use non-owning raw pointers for the fast build algorithm ---
|
||||
std::vector<Reaction*> remainingReactions;
|
||||
@@ -143,9 +183,9 @@ namespace gridfire {
|
||||
LOG_INFO(logger, "Starting network construction with {} available species.", availableSpecies.size());
|
||||
|
||||
for (int layer = 0; layer < depth && !remainingReactions.empty(); ++layer) {
|
||||
size_t collectedThisLayer = 0;
|
||||
size_t collectedStrong = 0;
|
||||
size_t collectedWeak = 0;
|
||||
[[maybe_unused]] size_t collectedThisLayer = 0;
|
||||
[[maybe_unused]] size_t collectedStrong = 0;
|
||||
[[maybe_unused]] size_t collectedWeak = 0;
|
||||
LOG_TRACE_L1(logger, "Collecting reactions for layer {} with {} remaining reactions. Currently there are {} available species", layer, remainingReactions.size(), availableSpecies.size());
|
||||
std::vector<Reaction*> reactionsForNextPass;
|
||||
std::unordered_set<Species> newProductsThisLayer;
|
||||
@@ -185,9 +225,9 @@ namespace gridfire {
|
||||
break;
|
||||
}
|
||||
|
||||
size_t oldProductCount = availableSpecies.size();
|
||||
[[maybe_unused]] size_t oldProductCount = availableSpecies.size();
|
||||
availableSpecies.insert(newProductsThisLayer.begin(), newProductsThisLayer.end());
|
||||
size_t newProductCount = availableSpecies.size() - oldProductCount;
|
||||
[[maybe_unused]] size_t newProductCount = availableSpecies.size() - oldProductCount;
|
||||
LOG_TRACE_L1(
|
||||
logger,
|
||||
"Layer {}: Collected {} new reactions ({} strong, {} weak). New products this layer: {}",
|
||||
|
||||
@@ -936,24 +936,30 @@ namespace gridfire {
|
||||
throw exceptions::StaleEngineError("Failed to get net species timescales due to stale engine state");
|
||||
}
|
||||
const std::unordered_map<Species, double>& destruction_timescales = destructionTimescale.value();
|
||||
const std::unordered_map<Species, double>& net_timescales = netTimescale.value();
|
||||
[[maybe_unused]] const std::unordered_map<Species, double>& net_timescales = netTimescale.value();
|
||||
|
||||
|
||||
for (const auto& [species, destruction_timescale] : destruction_timescales) {
|
||||
LOG_TRACE_L3(m_logger, "For {} destruction timescale is {} s", species.name(), destruction_timescale);
|
||||
}
|
||||
LOG_TRACE_L3(
|
||||
m_logger,
|
||||
"{}",
|
||||
[&]() -> std::string {
|
||||
std::stringstream ss;
|
||||
for (const auto& [species, destruction_timescale] : destruction_timescales) {
|
||||
ss << std::format("For {} destruction timescale is {}s\n", species.name(), destruction_timescale);
|
||||
}
|
||||
return ss.str();
|
||||
}()
|
||||
);
|
||||
|
||||
const auto& all_species = m_baseEngine.getNetworkSpecies();
|
||||
|
||||
std::vector<std::pair<double, Species>> sorted_destruction_timescales;
|
||||
for (const auto & species : all_species) {
|
||||
double destruction_timescale = destruction_timescales.at(species);
|
||||
double net_timescale = net_timescales.at(species);
|
||||
if (std::isfinite(destruction_timescale) && destruction_timescale > 0) {
|
||||
LOG_TRACE_L3(m_logger, "Species {} has finite destruction timescale: destruction: {} s, net: {} s", species.name(), destruction_timescale, net_timescale);
|
||||
LOG_TRACE_L3(m_logger, "Species {} has finite destruction timescale: destruction: {} s, net: {} s", species.name(), destruction_timescale, net_timescales.at(species));
|
||||
sorted_destruction_timescales.emplace_back(destruction_timescale, species);
|
||||
} else {
|
||||
LOG_TRACE_L3(m_logger, "Species {} has infinite or negative destruction timescale: destruction: {} s, net: {} s", species.name(), destruction_timescale, net_timescale);
|
||||
LOG_TRACE_L3(m_logger, "Species {} has infinite or negative destruction timescale: destruction: {} s, net: {} s", species.name(), destruction_timescale, net_timescales.at(species));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1093,7 +1099,6 @@ namespace gridfire {
|
||||
validated_groups.reserve(candidate_groups.size());
|
||||
for (auto& group : candidate_groups) {
|
||||
constexpr double FLUX_RATIO_THRESHOLD = 5;
|
||||
constexpr double LOG_FLOW_RATIO_THRESHOLD = 2;
|
||||
|
||||
const std::unordered_set<Species> algebraic_group_members(
|
||||
group.algebraic_species.begin(),
|
||||
@@ -1109,10 +1114,6 @@ namespace gridfire {
|
||||
double coupling_flux = 0.0;
|
||||
double leakage_flux = 0.0;
|
||||
|
||||
// Values for validating if the group could physically be in equilibrium
|
||||
double creationFlux = 0.0;
|
||||
double destructionFlux = 0.0;
|
||||
|
||||
for (const auto& reaction: m_baseEngine.getNetworkReactions()) {
|
||||
const double flow = std::abs(m_baseEngine.calculateMolarReactionFlow(*reaction, comp, T9, rho));
|
||||
if (flow == 0.0) {
|
||||
@@ -1125,7 +1126,6 @@ namespace gridfire {
|
||||
has_internal_algebraic_reactant = true;
|
||||
LOG_TRACE_L3(m_logger, "Adjusting destruction flux (+= {} mol g^-1 s^-1) for QSEGroup due to reactant {} from reaction {}",
|
||||
flow, reactant.name(), reaction->id());
|
||||
destructionFlux += flow;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1137,7 +1137,6 @@ namespace gridfire {
|
||||
has_internal_algebraic_product = true;
|
||||
LOG_TRACE_L3(m_logger, "Adjusting creation flux (+= {} mol g^-1 s^-1) for QSEGroup due to product {} from reaction {}",
|
||||
flow, product.name(), reaction->id());
|
||||
creationFlux += flow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,7 +1185,7 @@ namespace gridfire {
|
||||
if (coupling_flux / leakage_flux > FLUX_RATIO_THRESHOLD) {
|
||||
LOG_TRACE_L1(
|
||||
m_logger,
|
||||
"Group containing {} is in equilibrium due to high coupling flux and balanced creation and destruction rate: <coupling: leakage flux = {}, coupling flux = {}, ratio = {} (Threshold: {})>, <creation: creation flux = {}, destruction flux = {}, ratio = {} order of mag (Threshold: {} order of mag)>",
|
||||
"Group containing {} is in equilibrium due to high coupling flux and balanced creation and destruction rate: <coupling: leakage flux = {}, coupling flux = {}, ratio = {} (Threshold: {})>",
|
||||
[&]() -> std::string {
|
||||
std::stringstream ss;
|
||||
int count = 0;
|
||||
@@ -1202,18 +1201,14 @@ namespace gridfire {
|
||||
leakage_flux,
|
||||
coupling_flux,
|
||||
coupling_flux / leakage_flux,
|
||||
FLUX_RATIO_THRESHOLD,
|
||||
std::log10(creationFlux),
|
||||
std::log10(destructionFlux),
|
||||
std::abs(std::log10(creationFlux) - std::log10(destructionFlux)),
|
||||
LOG_FLOW_RATIO_THRESHOLD
|
||||
FLUX_RATIO_THRESHOLD
|
||||
);
|
||||
validated_groups.emplace_back(group);
|
||||
validated_groups.back().is_in_equilibrium = true;
|
||||
} else {
|
||||
LOG_TRACE_L1(
|
||||
m_logger,
|
||||
"Group containing {} is NOT in equilibrium: <coupling: leakage flux = {}, coupling flux = {}, ratio = {} (Threshold: {})>, <creation: creation flux = {}, destruction flux = {}, ratio = {} order of mag (Threshold: {} order of mag)>",
|
||||
"Group containing {} is NOT in equilibrium: <coupling: leakage flux = {}, coupling flux = {}, ratio = {} (Threshold: {})>",
|
||||
[&]() -> std::string {
|
||||
std::stringstream ss;
|
||||
int count = 0;
|
||||
@@ -1229,11 +1224,7 @@ namespace gridfire {
|
||||
leakage_flux,
|
||||
coupling_flux,
|
||||
coupling_flux / leakage_flux,
|
||||
FLUX_RATIO_THRESHOLD,
|
||||
std::log10(creationFlux),
|
||||
std::log10(destructionFlux),
|
||||
std::abs(std::log10(creationFlux) - std::log10(destructionFlux)),
|
||||
LOG_FLOW_RATIO_THRESHOLD
|
||||
FLUX_RATIO_THRESHOLD
|
||||
);
|
||||
invalidated_groups.emplace_back(group);
|
||||
invalidated_groups.back().is_in_equilibrium = false;
|
||||
|
||||
@@ -397,6 +397,12 @@ namespace gridfire::reaction {
|
||||
m_reactionNameMap.emplace(std::move(reaction_id), new_index);
|
||||
}
|
||||
|
||||
void ReactionSet::extend(const ReactionSet &other) {
|
||||
for (const auto& reaction : other.m_reactions) {
|
||||
add_reaction(*reaction);
|
||||
}
|
||||
}
|
||||
|
||||
void ReactionSet::remove_reaction(const Reaction& reaction) {
|
||||
const auto reaction_id = std::string(reaction.id());
|
||||
if (!m_reactionNameMap.contains(reaction_id)) {
|
||||
|
||||
@@ -195,7 +195,8 @@ namespace gridfire::solver {
|
||||
std::rethrow_exception(std::make_exception_ptr(*user_data.captured_exception));
|
||||
}
|
||||
|
||||
// log_step_diagnostics(user_data, false);
|
||||
// log_step_diagnostics(user_data, true);
|
||||
// exit(0);
|
||||
check_cvode_flag(flag, "CVode");
|
||||
|
||||
long int n_steps;
|
||||
|
||||
@@ -23,30 +23,30 @@ PYBIND11_MODULE(gridfire, m) {
|
||||
auto typeMod = m.def_submodule("type", "GridFire type bindings");
|
||||
register_type_bindings(typeMod);
|
||||
|
||||
auto partitionMod = m.def_submodule("partition", "GridFire partition function bindings");
|
||||
register_partition_bindings(partitionMod);
|
||||
|
||||
auto expectationMod = m.def_submodule("expectations", "GridFire expectations bindings");
|
||||
register_expectation_bindings(expectationMod);
|
||||
|
||||
auto reactionMod = m.def_submodule("reaction", "GridFire reaction bindings");
|
||||
register_reaction_bindings(reactionMod);
|
||||
|
||||
auto screeningMod = m.def_submodule("screening", "GridFire plasma screening bindings");
|
||||
register_screening_bindings(screeningMod);
|
||||
|
||||
auto ioMod = m.def_submodule("io", "GridFire io bindings");
|
||||
register_io_bindings(ioMod);
|
||||
|
||||
auto exceptionMod = m.def_submodule("exceptions", "GridFire exceptions bindings");
|
||||
register_exception_bindings(exceptionMod);
|
||||
|
||||
auto engineMod = m.def_submodule("engine", "Engine and Engine View bindings");
|
||||
register_engine_bindings(engineMod);
|
||||
|
||||
auto solverMod = m.def_submodule("solver", "GridFire numerical solver bindings");
|
||||
register_solver_bindings(solverMod);
|
||||
|
||||
auto utilsMod = m.def_submodule("utils", "GridFire utility method bindings");
|
||||
register_utils_bindings(utilsMod);
|
||||
// auto partitionMod = m.def_submodule("partition", "GridFire partition function bindings");
|
||||
// register_partition_bindings(partitionMod);
|
||||
//
|
||||
// auto expectationMod = m.def_submodule("expectations", "GridFire expectations bindings");
|
||||
// register_expectation_bindings(expectationMod);
|
||||
//
|
||||
// auto reactionMod = m.def_submodule("reaction", "GridFire reaction bindings");
|
||||
// register_reaction_bindings(reactionMod);
|
||||
//
|
||||
// auto screeningMod = m.def_submodule("screening", "GridFire plasma screening bindings");
|
||||
// register_screening_bindings(screeningMod);
|
||||
//
|
||||
// auto ioMod = m.def_submodule("io", "GridFire io bindings");
|
||||
// register_io_bindings(ioMod);
|
||||
//
|
||||
// auto exceptionMod = m.def_submodule("exceptions", "GridFire exceptions bindings");
|
||||
// register_exception_bindings(exceptionMod);
|
||||
//
|
||||
// auto engineMod = m.def_submodule("engine", "Engine and Engine View bindings");
|
||||
// register_engine_bindings(engineMod);
|
||||
//
|
||||
// auto solverMod = m.def_submodule("solver", "GridFire numerical solver bindings");
|
||||
// register_solver_bindings(solverMod);
|
||||
//
|
||||
// auto utilsMod = m.def_submodule("utils", "GridFire utility method bindings");
|
||||
// register_utils_bindings(utilsMod);
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
subdir('types')
|
||||
subdir('utils')
|
||||
subdir('expectations')
|
||||
subdir('exceptions')
|
||||
subdir('io')
|
||||
subdir('partition')
|
||||
subdir('reaction')
|
||||
subdir('screening')
|
||||
subdir('engine')
|
||||
subdir('solver')
|
||||
#subdir('utils')
|
||||
#subdir('expectations')
|
||||
#subdir('exceptions')
|
||||
#subdir('io')
|
||||
#subdir('partition')
|
||||
#subdir('reaction')
|
||||
#subdir('screening')
|
||||
#subdir('engine')
|
||||
#subdir('solver')
|
||||
|
||||
@@ -115,7 +115,7 @@ int main(int argc, char* argv[]){
|
||||
// netIn.tMax = 1e-14;
|
||||
netIn.dt0 = 1e-12;
|
||||
|
||||
GraphEngine ReaclibEngine(composition, partitionFunction, NetworkBuildDepth::SecondOrder);
|
||||
GraphEngine ReaclibEngine(composition, partitionFunction, NetworkBuildDepth::SecondOrder, NetworkConstructionFlags::STRONG );
|
||||
|
||||
ReaclibEngine.setPrecomputation(true);
|
||||
ReaclibEngine.setUseReverseReactions(false);
|
||||
|
||||
@@ -72,7 +72,7 @@ TEST_F(approx8Test, reaclib) {
|
||||
fourdst::composition::Composition composition;
|
||||
composition.registerSymbol(symbols, true);
|
||||
composition.setMassFraction(symbols, comp);
|
||||
composition.finalize(true);
|
||||
[[maybe_unused]] bool didFinalize = composition.finalize(true);
|
||||
|
||||
|
||||
NetIn netIn;
|
||||
|
||||
Reference in New Issue
Block a user