perf(graph_engine): finished sparsity system for jacobian, major preformance win, roughly 20x faster

essentially all callers can now inform the graph engine about which species they hold active and graph engine then uses those to define a sparsity pattern and only calculate the jacobian along that sparsity pattern
This commit is contained in:
2025-10-24 11:17:22 -04:00
parent 0581f69c48
commit 98db2b1d43
14 changed files with 441 additions and 66 deletions

View File

@@ -2,6 +2,9 @@
#include <cstdint>
#include "gridfire/exceptions/exceptions.h"
#include "gridfire/reaction/reaction.h"
namespace gridfire::utils {
/**
* @brief Generate a unique hash for an isotope given its mass number (A) and atomic number (Z).
@@ -16,4 +19,47 @@ namespace gridfire::utils {
return (static_cast<uint_fast32_t>(a) << 8) | static_cast<uint_fast32_t>(z);
}
}
namespace hashing::reaction {
static std::uint64_t splitmix64(std::uint64_t x) noexcept {
x += 0x9E3779B97F4A7C15ULL;
x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ULL;
x = (x ^ (x >> 27)) * 0x94D049BB133111EBULL;
x ^= (x >> 31);
return x;
}
static std::uint64_t mix_species(const unsigned a, const unsigned z) noexcept {
const std::uint64_t code = (static_cast<std::uint64_t>(a) << 7) | static_cast<std::uint64_t>(z);
return splitmix64(code);
}
static std::uint64_t multiset_combine(std::uint64_t acc, const std::uint64_t x) noexcept {
acc += x;
acc ^= (x << 23) | (x >> (64 - 23));
acc = splitmix64(acc);
return acc;
}
}
inline std::uint64_t hash_reaction(const reaction::Reaction& reaction) noexcept {
using namespace hashing::reaction;
std::uint64_t hR = 0;
for (const auto& s : reaction.reactants()) {
hR = multiset_combine(hR, mix_species(static_cast<unsigned>(s.a()),
static_cast<unsigned>(s.z())));
}
std::uint64_t hP = 0;
for (const auto& s : reaction.products()) {
hP = multiset_combine(hP, mix_species(static_cast<unsigned>(s.a()),
static_cast<unsigned>(s.z())));
}
std::uint64_t h = splitmix64(hR ^ 0xC3A5C85C97CB3127ULL);
h ^= splitmix64((hP << 1) | (hP >> 63));
return splitmix64(h);
}
}