post_process.py — Derived quantities for RadCluster_2_1.
Computes macroscopic observables from the ODE solution, including:
- Total SIA / vacancy / He contents
- Mean cluster sizes
- Void swelling via the swelling identity (Eq. 161)
- Frenkel pair conservation diagnostic δ_FP (Eq. 164)
- He conservation diagnostic δ_He (Eq. 165)
Physics reference
-----------------
Ghoniem, N.M. (2026), Section 7 (Rate_Equations.pdf):
Eqs. 161-165.
| py_utils.post_process._floor_bin_moments |
( |
|
mu0_raw, |
|
|
|
mu1_raw, |
|
|
|
nlo, |
|
|
|
nhi, |
|
|
|
C_floor, |
|
|
|
P |
|
) |
| |
|
protected |
Remove the uniform C_floor IC from a bin's moments, CONSISTENTLY.
For a bin spanning [nlo, nhi) of width Δ, the uniform C_floor initial
condition contributes Δ·C_floor to μ₀ and C_floor·Δ·(nlo+nhi−1)/2 to μ₁.
Subtracting them is exact — but clamping each at zero INDEPENDENTLY is not:
a near-empty bin can clamp μ₀ to exactly 0 while μ₁ stays positive, i.e. an
empty bin that still carries content. Summed over bins that inflates the
content while the count collapses, and content/count — the reported mean
size — diverges. That is how ``mean_n_100`` reached 2853 on a grid of
I = 1000, a value arithmetically impossible for a mean size, and why
``bin_moment`` + ``loop_conversion`` appeared to fail silently.
The bug is NOT conversion-specific: the same pattern governed ``mean_n_i``
and ``mean_n_v``. It stayed latent there only because the ½⟨111⟩ and
vacancy bins are normally well populated, whereas the ⟨100⟩ population is
near-empty for most of a run (it exists only by conversion) and so sits in
the pathological regime continuously. It still bites the others in the
early transient and in the large-size tail.
Two couplings restore consistency, mirroring the guard the C++
reconstruction already applies (``rate_kernels.cpp``, "clamp n_bar into the
bin"):
(a) an empty bin carries no content;
(b) a bin's mean size must lie inside the bin, i.e. μ₁/μ₀ ∈ [nlo, nhi−1].
Accepts scalars or arrays (the ⟨100⟩ path passes whole time series).
Definition at line 22 of file post_process.py.