|
| | n_moments_for_shape (shape_function) |
| |
| | build_bins (N_max, n1=1, r=2.0) |
| |
| | moments_from_distribution (c_n, bins, n_mom=2) |
| |
| | distribution_from_moments_pc (mu0, mu1, bins, N_max) |
| |
| | midpoint_distribution_from_moments (mu0, mu1, bins, mu2=None, shape_function='linear') |
| |
| | distribution_from_moments_hat (mu0, mu1, bins, N_max) |
| |
| | distribution_from_moments_lognormal (mu0, mu1, mu2, bins, N_max) |
| |
| | reconstruct_distribution (shape_function, mu0, mu1, mu2, bins, N_max, *smooth_edges=False) |
| |
| | _smooth_bin_edges_inplace (c_n, bins) |
| |
| | distribution_from_moments_continuous (mu0, mu1, bins, N_max) |
| |
bin_moment_rates.py — Size-bin moment reduction for RadCluster_2_1.
REFERENCE ONLY (ODE RHS) — the `ode_system` method of
BinMomentRateEquations is not used by the solver; the production RHS is the
C++ implementation. May be stale. Scheduled for replacement by the
Stage-3 graph-walker. simulation.py integrates exclusively via the C++
solver and never calls the Python `ode_system`. Note that the
reconstruction/projection helpers and bin-construction code in this module
ARE used (e.g. by simulation.py's adaptive domain expansion); only the
`ode_system` RHS is dead code.
Implements the Chapter 9 state-space reduction for the SIA and vacancy
cluster populations via logarithmic size bins. Three intra-bin shape
functions (closures) are supported:
shape_function = "constant" — piecewise-constant (1 moment/bin: μ₀)
shape_function = "linear" — hat-function / dual-basis (2 moments/bin: μ₀, μ₁)
shape_function = "lognormal" — log-normal (3 moments/bin: μ₀, μ₁, μ₂)
Physics reference
-----------------
Ghoniem, N.M. (2026), Chapter 9 (Rate_Equations.pdf):
Eqs. 188-211.
Bin partition (Eq. 188)
-----------------------
Logarithmic bin edges:
n_k = floor(n_1 · r^k), k = 0, 1, ..., K_bins
r > 1 (typically r = 2)
Bin B_k = {n : n_k ≤ n < n_{k+1}} (Eq. 189)
Bin width |B_k| = n_{k+1} − n_k (Eq. 190)
Bin moments (Eq. 192)
---------------------
μ_k^(0) = Σ_{n ∈ B_k} c_n (zeroth — bin density)
μ_k^(1) = Σ_{n ∈ B_k} n · c_n (first — bin content)
μ_k^(2) = Σ_{n ∈ B_k} n² · c_n (second — used only by lognormal)
Closures
--------
Piecewise-constant (Eq. 198-200):
c_n ≈ μ_k^(0) / |B_k| for all n ∈ B_k
Hat-function / linear (Galerkin) (Eq. 201-206):
c_n = φ_{k,0}(n) · μ_k^(0) + φ_{k,1}(n) · μ_k^(1)
Log-normal (Eq. 213-216):
c_n ∝ (1/n) exp[−(ln n − m_k)² / (2σ_k²)]
with m_k, σ_k determined from μ₀, μ₁, μ₂; normalized to preserve μ₀.
| py_utils.bin_moment_rates.distribution_from_moments_continuous |
( |
|
mu0, |
|
|
|
mu1, |
|
|
|
bins, |
|
|
|
N_max |
|
) |
| |
Reconstruct per-size concentrations with C⁰ continuity across bin edges.
At each internal bin boundary, the left and right hat-function values
are averaged. Within each bin, linear interpolation between the
(averaged) edge values replaces the raw hat function. This removes
the staircase discontinuities visible in the standard reconstruction
while preserving the bin moments to first order.
Parameters
----------
mu0, mu1 : ndarray [K_bins]
bins : list of (n_lo, n_hi)
N_max : int
Returns
-------
c_n : ndarray [N_max]
Definition at line 483 of file bin_moment_rates.py.
| py_utils.bin_moment_rates.distribution_from_moments_hat |
( |
|
mu0, |
|
|
|
mu1, |
|
|
|
bins, |
|
|
|
N_max |
|
) |
| |
Reconstruct per-size concentrations from moments using a linear
dual-basis that exactly preserves both μ₀ and μ₁.
Shape functions (linear dual basis):
φ₀(n) = (S₂ − S₁·n) / Δ
φ₁(n) = (bw·n − S₁) / Δ
where
S₁ = Σ n, S₂ = Σ n², Δ = bw·S₂ − S₁²
This guarantees:
Σ φ₀ = 1, Σ φ₁ = 0 → Σ cₙ = μ₀
Σ n·φ₀ = 0, Σ n·φ₁ = 1 → Σ n·cₙ = μ₁
Negative values are clamped to 0 (breaks exact preservation for
strongly skewed bins, but keeps concentrations physical).
Parameters
----------
mu0, mu1 : ndarray [K_bins]
bins : list of (n_lo, n_hi)
N_max : int
Returns
-------
c_n : ndarray [N_max]
Definition at line 240 of file bin_moment_rates.py.
| py_utils.bin_moment_rates.distribution_from_moments_lognormal |
( |
|
mu0, |
|
|
|
mu1, |
|
|
|
mu2, |
|
|
|
bins, |
|
|
|
N_max |
|
) |
| |
Reconstruct per-size concentrations from moments using a log-normal
intra-bin shape function (Eq. 213-216).
Within each bin B_k, the distribution is assumed to follow:
c_n ∝ (1/n) exp[−(ln n − m_k)² / (2σ_k²)]
The two log-normal parameters are determined from the moments:
n_bar = μ₁/μ₀
n2_bar = μ₂/μ₀
σ_k² = ln(n2_bar / n_bar²) = ln(μ₂·μ₀ / μ₁²)
m_k = ln(n_bar) − σ_k²/2
The amplitude is set so that Σ_{n∈B_k} c_n = μ₀ exactly.
Falls back to linear (hat-function) closure when σ_k² ≤ 0
(monodisperse limit), and to piecewise-constant when the bin
has only one size.
Parameters
----------
mu0, mu1, mu2 : ndarray [K_bins]
bins : list of (n_lo, n_hi)
N_max : int
Returns
-------
c_n : ndarray [N_max]
Definition at line 299 of file bin_moment_rates.py.
| py_utils.bin_moment_rates.moments_from_distribution |
( |
|
c_n, |
|
|
|
bins, |
|
|
|
n_mom = 2 |
|
) |
| |
Compute bin moments from per-size concentrations.
Parameters
----------
c_n : ndarray [N_max] — concentrations, c_n[n-1] = c_n
bins : list of (n_lo, n_hi)
n_mom : int — number of moments to compute (1, 2, or 3)
Returns
-------
mu0 : ndarray [K_bins] — zeroth moments
mu1 : ndarray [K_bins] or None — first moments (if n_mom >= 2)
mu2 : ndarray [K_bins] or None — second moments (if n_mom >= 3)
Definition at line 102 of file bin_moment_rates.py.
| py_utils.bin_moment_rates.reconstruct_distribution |
( |
|
shape_function, |
|
|
|
mu0, |
|
|
|
mu1, |
|
|
|
mu2, |
|
|
|
bins, |
|
|
|
N_max, |
|
|
* |
smooth_edges = False |
|
) |
| |
Dispatch to the appropriate reconstruction function.
Parameters
----------
shape_function : str — "constant", "linear", or "lognormal"
mu0 : ndarray [K]
mu1 : ndarray [K] or None
mu2 : ndarray [K] or None
bins : list of (n_lo, n_hi)
N_max : int
smooth_edges : bool, default False
If True, post-process the reconstructed distribution by averaging
the two values straddling each internal bin boundary (geometric
mean in log-space) and rescaling each bin so that
Σ_{n ∈ B_k} c_n equals its pre-smoothing sum, preserving μ_k^(0)
exactly. Use for visualization only — ODE right-hand sides and
conservation diagnostics must pass False.
Returns
-------
c_n : ndarray [N_max]
Definition at line 392 of file bin_moment_rates.py.