fix(AtomicWeakRate): added bool overrides for sparsity calculations

these allow the atomic weak rate to be used with the current sparsity code. Note also that this commit reintroduces the full weak reaction set which does introduce an enormouse degree of stiffness which will need to be filtered out. What this means is that this commit practically cannot evolve a network due to this stiffness
This commit is contained in:
2025-10-31 07:38:04 -04:00
parent 1af54132b8
commit 56f9342052
4 changed files with 113 additions and 57 deletions

View File

@@ -473,6 +473,20 @@ namespace gridfire::rates::weak {
CppAD::vector<std::set<size_t>>& st CppAD::vector<std::set<size_t>>& st
) override; ) override;
bool for_sparse_jac(
size_t q,
const CppAD::vector<bool> &r,
CppAD::vector<bool> &s,
const CppAD::vector<double> &x
) override;
bool rev_sparse_jac(
size_t q,
const CppAD::vector<bool> &rt,
CppAD::vector<bool> &st,
const CppAD::vector<double> &x
) override;
private: private:
const WeakRateInterpolator& m_interpolator; const WeakRateInterpolator& m_interpolator;
const size_t m_a; const size_t m_a;
@@ -536,7 +550,7 @@ namespace gridfire::rates::weak {
T rateConstant = static_cast<T>(0.0); T rateConstant = static_cast<T>(0.0);
if constexpr (std::is_same_v<T, CppAD::AD<double>>) { // Case where T is an AD type if constexpr (std::is_same_v<T, CppAD::AD<double>>) { // Case where T is an AD type
std::vector<T> ax = {T9, log_rhoYe, mue}; std::vector<T> ax = {T9, log_rhoYe};
std::vector<T> ay(2); std::vector<T> ay(2);
m_atomic(ax, ay); m_atomic(ax, ay);
rateConstant = static_cast<T>(ay[0]); rateConstant = static_cast<T>(ay[0]);

View File

@@ -1407,7 +1407,7 @@ namespace gridfire {
} }
bool GraphEngine::AtomicReverseRate::reverse( bool GraphEngine::AtomicReverseRate::reverse(
size_t q, const size_t q,
const CppAD::vector<double> &tx, const CppAD::vector<double> &tx,
const CppAD::vector<double> &ty, const CppAD::vector<double> &ty,
CppAD::vector<double> &px, CppAD::vector<double> &px,
@@ -1424,7 +1424,7 @@ namespace gridfire {
} }
bool GraphEngine::AtomicReverseRate::for_sparse_jac( bool GraphEngine::AtomicReverseRate::for_sparse_jac(
size_t q, const size_t q,
const CppAD::vector<std::set<size_t>> &r, const CppAD::vector<std::set<size_t>> &r,
CppAD::vector<std::set<size_t>> &s CppAD::vector<std::set<size_t>> &s
) { ) {
@@ -1433,7 +1433,7 @@ namespace gridfire {
} }
bool GraphEngine::AtomicReverseRate::rev_sparse_jac( bool GraphEngine::AtomicReverseRate::rev_sparse_jac(
size_t q, const size_t q,
const CppAD::vector<std::set<size_t>> &rt, const CppAD::vector<std::set<size_t>> &rt,
CppAD::vector<std::set<size_t>> &st CppAD::vector<std::set<size_t>> &st
) { ) {
@@ -1442,7 +1442,7 @@ namespace gridfire {
} }
bool GraphEngine::AtomicReverseRate::for_sparse_jac( bool GraphEngine::AtomicReverseRate::for_sparse_jac(
size_t q, const size_t q,
const CppAD::vector<bool> &r, const CppAD::vector<bool> &r,
CppAD::vector<bool> &s, CppAD::vector<bool> &s,
const CppAD::vector<double> &x const CppAD::vector<double> &x
@@ -1450,8 +1450,8 @@ namespace gridfire {
constexpr size_t n = 1; constexpr size_t n = 1;
constexpr size_t m = 1; constexpr size_t m = 1;
CPPAD_ASSERT_KNOWN(r.size() == n * q, "for_sparse_jac: 'r' size is incorrect."); CPPAD_ASSERT_KNOWN(r.size() == n * q, "AtomicReverseRate::for_sparse_jac: 'r' size is incorrect.");
CPPAD_ASSERT_KNOWN(s.size() == m * q, "for_sparse_jac: 's' size is incorrect."); CPPAD_ASSERT_KNOWN(s.size() == m * q, "AtomicReverseRate::for_sparse_jac: 's' size is incorrect.");
// S = R // S = R
for (size_t j = 0; j < q; j++) { for (size_t j = 0; j < q; j++) {
@@ -1463,7 +1463,7 @@ namespace gridfire {
} }
bool GraphEngine::AtomicReverseRate::rev_sparse_jac( bool GraphEngine::AtomicReverseRate::rev_sparse_jac(
size_t q, const size_t q,
const CppAD::vector<bool> &rt, const CppAD::vector<bool> &rt,
CppAD::vector<bool> &st, CppAD::vector<bool> &st,
const CppAD::vector<double> &x const CppAD::vector<double> &x
@@ -1471,8 +1471,8 @@ namespace gridfire {
constexpr size_t n = 1; constexpr size_t n = 1;
constexpr size_t m = 1; constexpr size_t m = 1;
CPPAD_ASSERT_KNOWN(rt.size() == n * q, "for_sparse_jac: 'r' size is incorrect."); CPPAD_ASSERT_KNOWN(rt.size() == n * q, "AtomicReverseRate::for_sparse_jac: 'r' size is incorrect.");
CPPAD_ASSERT_KNOWN(st.size() == m * q, "for_sparse_jac: 's' size is incorrect."); CPPAD_ASSERT_KNOWN(st.size() == m * q, "AtomicReverseRate::for_sparse_jac: 's' size is incorrect.");
// st = rt // st = rt
for (size_t j = 0; j < q; j++) { for (size_t j = 0; j < q; j++) {

View File

@@ -76,48 +76,48 @@ namespace gridfire {
} }
// --- Clone all possible weak reactions into the master reaction pool --- // --- Clone all possible weak reactions into the master reaction pool ---
// for (const auto& parent_species: weakInterpolator.available_isotopes()) { for (const auto& parent_species: weakInterpolator.available_isotopes()) {
// std::expected<Species, fourdst::atomic::SpeciesErrorType> upProduct = fourdst::atomic::az_to_species( std::expected<Species, fourdst::atomic::SpeciesErrorType> upProduct = fourdst::atomic::az_to_species(
// parent_species.a(), parent_species.a(),
// parent_species.z() + 1 parent_species.z() + 1
// ); );
// std::expected<Species, fourdst::atomic::SpeciesErrorType> downProduct = fourdst::atomic::az_to_species( std::expected<Species, fourdst::atomic::SpeciesErrorType> downProduct = fourdst::atomic::az_to_species(
// parent_species.a(), parent_species.a(),
// parent_species.z() - 1 parent_species.z() - 1
// ); );
// if (downProduct.has_value()) { // Only add the reaction if the Species map contains the product if (downProduct.has_value()) { // Only add the reaction if the Species map contains the product
// master_reaction_pool.add_reaction( master_reaction_pool.add_reaction(
// std::make_unique<rates::weak::WeakReaction>( std::make_unique<rates::weak::WeakReaction>(
// parent_species, parent_species,
// rates::weak::WeakReactionType::BETA_PLUS_DECAY, rates::weak::WeakReactionType::BETA_PLUS_DECAY,
// weakInterpolator weakInterpolator
// ) )
// ); );
// master_reaction_pool.add_reaction( master_reaction_pool.add_reaction(
// std::make_unique<rates::weak::WeakReaction>( std::make_unique<rates::weak::WeakReaction>(
// parent_species, parent_species,
// rates::weak::WeakReactionType::ELECTRON_CAPTURE, rates::weak::WeakReactionType::ELECTRON_CAPTURE,
// weakInterpolator weakInterpolator
// ) )
// ); );
// } }
// if (upProduct.has_value()) { // Only add the reaction if the Species map contains the product if (upProduct.has_value()) { // Only add the reaction if the Species map contains the product
// master_reaction_pool.add_reaction( master_reaction_pool.add_reaction(
// std::make_unique<rates::weak::WeakReaction>( std::make_unique<rates::weak::WeakReaction>(
// parent_species, parent_species,
// rates::weak::WeakReactionType::BETA_MINUS_DECAY, rates::weak::WeakReactionType::BETA_MINUS_DECAY,
// weakInterpolator weakInterpolator
// ) )
// ); );
// master_reaction_pool.add_reaction( master_reaction_pool.add_reaction(
// std::make_unique<rates::weak::WeakReaction>( std::make_unique<rates::weak::WeakReaction>(
// parent_species, parent_species,
// rates::weak::WeakReactionType::POSITRON_CAPTURE, rates::weak::WeakReactionType::POSITRON_CAPTURE,
// weakInterpolator weakInterpolator
// ) )
// ); );
// } }
// } // TODO: Remove comments, weak reactions have been disabled for testing } // TODO: Remove comments, weak reactions have been disabled for testing
// --- Step 2: Use non-owning raw pointers for the fast build algorithm --- // --- Step 2: Use non-owning raw pointers for the fast build algorithm ---
std::vector<Reaction*> remainingReactions; std::vector<Reaction*> remainingReactions;

View File

@@ -382,7 +382,7 @@ namespace gridfire::rates::weak {
) const { ) const {
const CppAD::AD<double> log_rhoYe = CppAD::log10(rho * Ye); const CppAD::AD<double> log_rhoYe = CppAD::log10(rho * Ye);
const std::vector<CppAD::AD<double>> ax = {T9, log_rhoYe, mue}; const std::vector<CppAD::AD<double>> ax = {T9, log_rhoYe};
std::vector<CppAD::AD<double>> ay(2); // 2 outputs are the reaction rate (1/s) and the neutrino loss (MeV) std::vector<CppAD::AD<double>> ay(2); // 2 outputs are the reaction rate (1/s) and the neutrino loss (MeV)
m_atomic(ax, ay); // Note: We needed to make m_atomic mutable to allow this call in a const method. m_atomic(ax, ay); // Note: We needed to make m_atomic mutable to allow this call in a const method.
@@ -491,7 +491,7 @@ namespace gridfire::rates::weak {
return logNeutrinoLoss; return logNeutrinoLoss;
} }
// Note that the input vector tx is of size 3: [T9, log10(rho*Ye), mu_e] // Note that the input vector tx is of size 2: [T9, log10(rho*Ye)]
bool WeakReaction::AtomicWeakRate::forward ( bool WeakReaction::AtomicWeakRate::forward (
const size_t p, const size_t p,
const size_t q, const size_t q,
@@ -549,7 +549,7 @@ namespace gridfire::rates::weak {
} }
bool WeakReaction::AtomicWeakRate::reverse( bool WeakReaction::AtomicWeakRate::reverse(
size_t q, const size_t q,
const CppAD::vector<double> &tx, const CppAD::vector<double> &tx,
const CppAD::vector<double> &ty, const CppAD::vector<double> &ty,
CppAD::vector<double> &px, CppAD::vector<double> &px,
@@ -624,7 +624,7 @@ namespace gridfire::rates::weak {
} }
bool WeakReaction::AtomicWeakRate::for_sparse_jac( bool WeakReaction::AtomicWeakRate::for_sparse_jac(
size_t q, const size_t q,
const CppAD::vector<std::set<size_t> > &r, const CppAD::vector<std::set<size_t> > &r,
CppAD::vector<std::set<size_t> > &s CppAD::vector<std::set<size_t> > &s
) { ) {
@@ -640,7 +640,7 @@ namespace gridfire::rates::weak {
} }
bool WeakReaction::AtomicWeakRate::rev_sparse_jac( bool WeakReaction::AtomicWeakRate::rev_sparse_jac(
size_t q, const size_t q,
const CppAD::vector<std::set<size_t> > &rt, const CppAD::vector<std::set<size_t> > &rt,
CppAD::vector<std::set<size_t> > &st CppAD::vector<std::set<size_t> > &st
) { ) {
@@ -655,11 +655,53 @@ namespace gridfire::rates::weak {
} }
bool WeakReaction::AtomicWeakRate::for_sparse_jac(
const size_t q,
const CppAD::vector<bool> &r,
CppAD::vector<bool> &s,
const CppAD::vector<double> &x
) {
constexpr size_t n = 2; // Number of inputs
constexpr size_t m = 2; // Number of outputs
CPPAD_ASSERT_KNOWN(r.size() == q * n, "AtomicWeakRate::for_sparse_jac: 'r' size is incorrect!");
CPPAD_ASSERT_KNOWN(s.size() == q * m, "AtomicWeakRate::for_sparse_jac: 's' size is incorrect!");
// Both outputs depend on both inputs
// s[i + j*m] represents s(i,j) - output i, direction j
// r[k + j*n] represents r(k,j) - input k, direction j
for (size_t j = 0; j < q; j++) {
// s(0,j) = r(0,j) || r(1,j) --- output 0 depends on both inputs
s[0 + j*m] = r[0 + j*n] || r[1 + j*n];
// s(1,j) = r(0,j) || r(1,j) --- output 1 depends on both inputs
s[1 + j*m] = r[0 + j*n] || r[1 + j*n];
}
return true;
}
bool WeakReaction::AtomicWeakRate::rev_sparse_jac(
const size_t q,
const CppAD::vector<bool> &rt,
CppAD::vector<bool> &st,
const CppAD::vector<double> &x
) {
constexpr size_t n = 2; // Number of inputs
constexpr size_t m = 2; // Number of outputs
CPPAD_ASSERT_KNOWN(rt.size() == q * m, "AtomicWeakRate::rev_sparse_jac: 'rt' size is incorrect!");
CPPAD_ASSERT_KNOWN(st.size() == q * n, "AtomicWeakRate::rev_sparse_jac: 'st' size is incorrect!");
for (size_t j = 0; j < q; j++) {
//st(0,j) = rt(0,j) || rt(1,j) --- input 0 affects both outputs
st[0 + j*n] = rt[0 + j*m] || rt[1 + j*m];
//st(1,j) = rt(0,j) || rt(1,j) --- input 1 affects both outputs
st[1 + j*n] = rt[0 + j*m] || rt[1 + j*m];
}
return true;
}
} }