reaction_rates.py — Pre-computed rate constant arrays for RadCluster_2_1.
Implements all capture, emission, trap-mutation, and re-solution rates for
the full per-size cluster dynamics system in bcc Fe / EUROFER97.
Physics reference
-----------------
Ghoniem, N.M. (2026), Sections 5-6 (Rate_Equations.pdf):
Eqs. 109-143, Tables 25, 26, 28, 30.
Key rate formulas
-----------------
Geometric prefactors (Eq. 128):
A_sph = (48π²)^{1/3} ≈ 7.818
A_loop = 8√(π/√3) ≈ 10.78
A_1D = 9/(8π^{2/3}) ≈ 2.632
B_rot = (4/π)(8π/3)^{1/3} ≈ 2.627
Spherical 3D capture (Eq. 109, 131):
K_sph(α, m) = A_sph · m^{1/3} · ω_α^eff [m^3/s per unit Ω]
Loop capture of SIA by dislocation loops (Eq. 113, 132):
K_loop(i, n) = A_loop · n^{1/2} · Z_i^loop · ω_i^eff
V–SIA recombination (Eq. P1, monodef_iv):
K_iv = 4√3·π · (ω_i^eff + ω_v^eff) [s^-1 per (at.frac)^2]
Mixed 1D/3D effective rate for glissile SIA clusters (Eq. 121, 141):
K_n,m^eff = A_sph · m^{1/3} · ω_n^{1D} / (1 + B_rot · L̂² · m^{-1/3})
Thermal emission (Eq. 122, 138-140):
α_α(m) = A_sph · (m-1)^{1/3} · ω_α^eff · exp(−E_b(m) / k_B T)
Fixed sinks (Eq. 134-137):
D_α^d = Z_α · ρ_d · ω_α^eff · a²
D_α^gb = π² · D_α^eff / d_g²
D_α^p = 4π · Z_p · ρ_p · r_p · D_α^eff (Eq. P4p; Z_p is a pure bias)
State vector convention
-----------------------
All rate constants are dimensionless per-atom-fraction quantities (unit = s^-1)
obtained by dividing the volumetric rate [m^3/s] by Ω [m^3].
This ensures: dC [at.frac/s] = K [s^-1 per at.frac] · C_A · C_B.
| py_utils.reaction_rates._opt_pos_float |
( |
|
v | ) |
|
|
protected |
Workbook cell → positive float, or None.
Returns None for an absent key, a blank cell (pandas NaN), a
non-numeric entry, or a non-positive value. Used for *optional override*
keys, where "not supplied" must be distinguishable from "supplied as 0"
and must fall back to the legacy code path rather than raise.
Definition at line 59 of file reaction_rates.py.
| py_utils.reaction_rates.effective_n_j_min |
( |
|
n_j_min_junc, |
|
|
|
i_mobile, |
|
|
|
frac = 0.6 |
|
) |
| |
Junction minimum size, made consistent with the mobility cutoff.
The Marian junction fires only when BOTH partners satisfy
``min(n, n') >= n_j_min_junc`` (``reaction_rates.phi_junc``,
``rate_kernels.cpp:conv_phi_junc``). But coalescence partners are mobile
clusters, so no partner can exceed ``i_mobile``. With the shipped
``n_j_min_junc = 30`` and ``i_mobile < 30`` the condition is unsatisfiable
and the junction channel is **identically zero** — measured 2026-07-31:
``phi_max_junc`` 0.1 and 1.0 gave bit-identical ``f_100`` at
``i_mobile = 10``.
That matters because ``i_mobile`` is sampled over 5-50 in the twin, so the
channel would switch on discontinuously at ``i_mobile = 30`` and
``phi_max_junc`` would screen as inert over most of the prior for a purely
structural reason.
Rule: ``n_j_min_eff = min(n_j_min_junc, ceil(frac * i_mobile))``, floored
at 2 (a junction needs at least two di-interstitials). With the default
``frac = 0.6`` this returns exactly ``n_j_min_junc`` at ``i_mobile = 50``
(0.6*50 = 30), so the production configuration is **unchanged** and every
existing result at ``i_mobile >= 50`` is bit-identical; the threshold only
relaxes where the mobility cutoff would otherwise make it unreachable.
Definition at line 96 of file reaction_rates.py.