Nucleide

Depletion

Burnup matrices, the Bateman equation, and the CRAM solver used by Nucleide.

Nucleide solves nuclide transmutation over a single time step using a burnup matrix formulation and the Chebyshev Rational Approximation Method (CRAM) for the matrix exponential.

Overview

For a vector of nuclide atom densities n(t)\mathbf{n}(t), the linearized depletion equation is

dndt=An,n(t)=eAtn(0),\frac{d\mathbf{n}}{dt} = \mathbf{A}\,\mathbf{n}, \qquad \mathbf{n}(t) = e^{\mathbf{A}t}\,\mathbf{n}(0),

where A\mathbf{A} is the burnup matrix. Each column of A\mathbf{A} describes how a parent nuclide is lost and what it produces; each row describes how a daughter nuclide is gained.

Where this lives in the code

Matrix construction is in crates/depletion/src/matrix.rs and the CRAM solver is in crates/depletion/src/cram.rs. The public driver is deplete in crates/depletion/src/lib.rs.

Building the burnup matrix

Nucleide builds A\mathbf{A} from a Chain and a set of one-group reaction rates.

Decay

For nuclide ii with half-life t1/2,it_{1/2,i}, the decay constant is

λi=ln2t1/2,i.\lambda_i = \frac{\ln 2}{t_{1/2,i}}.

The diagonal entry loses atoms at rate λi\lambda_i:

Aii  =  λi.A_{ii} \;\mathrel{-}=\; \lambda_i.

Each decay mode with branching ratio bijb_{i \to j} adds production to the off-diagonal:

Aji  +=  λibij.A_{ji} \;\mathrel{+}=\; \lambda_i \, b_{i \to j}.

Reactions

For a one-group reaction rate σϕ\sigma\phi of type rr on nuclide ii:

  • Loss: Aii=σϕA_{ii} \mathrel{-}= \sigma\phi once per reaction type, even if the chain lists multiple branched entries for that type.
  • Production: each reaction entry with branching ratio bb and target jj contributes Aji  +=  σϕb.A_{ji} \;\mathrel{+}=\; \sigma\phi \, b.
  • Light-particle secondaries: reactions such as (n,α)(n,\alpha), (n,p)(n,p), and (n,d)(n,d) emit light nuclides that are tracked when they appear in the chain (e.g. (n,α)He-4(n,\alpha) \to \mathrm{He\text{-}4}).
  • Fission: if fission yields yiky_{i \to k} are present, production is distributed over all fission products: Aki  +=  σϕyik.A_{ki} \;\mathrel{+}=\; \sigma\phi \, y_{i \to k}.

The final matrix A\mathbf{A} has units of s1\mathrm{s}^{-1} and is sparse, with one diagonal entry per chain nuclide even if it is stable.

CRAM: matrix exponential by partial fractions

CRAM evaluates the action of the matrix exponential eAte^{\mathbf{A}t} on n0\mathbf{n}_0 in incomplete partial fraction (IPF) product form:

nk  =  nk1  +  2Re ⁣[αk(AtθkI)1nk1],n(t)=α0nm,\mathbf{n}_k \;=\; \mathbf{n}_{k-1} \;+\; 2 \, \mathrm{Re}\!\left[ \alpha_k \, (\mathbf{A}t - \theta_k \mathbf{I})^{-1} \mathbf{n}_{k-1} \right], \qquad \mathbf{n}(t) = \alpha_0 \, \mathbf{n}_m,

where m=8m = 8 for order-16 and m=24m = 24 for order-48. The coefficients α0\alpha_0, αk\alpha_k, and θk\theta_k are pre-computed complex numbers published by Pusa. Each pole is applied sequentially to the running solution vector; these IPF coefficients are not interchangeable with the residues of the classic partial-fraction sum form.

Why the IPF product form?

Each step (AtθkI)1nk1(\mathbf{A}t - \theta_k \mathbf{I})^{-1}\mathbf{n}_{k-1} is a sparse linear solve rather than a full matrix exponential. Nucleide uses a sparse LU factorization from the linalg facade, and the symbolic pattern is reused across all poles.

Coefficients

Nucleide ships the CRAM-16 and CRAM-48 coefficient sets verbatim. CRAM-16 is cheaper; CRAM-48 is the production default.

kRe(θ)Im(θ)Re(α)Im(α)
13.5091036084149188.4361989858843745464.93057687021-37979.83575308356
25.9481522689511773.58745736201832290.45112476907548-1115.537522430261
3-5.26497134344264716.22022147316793234.4818070467641-422.8020157070496
41.41937589718566610.9253634844967294.53304067358312-295.1294291446048
56.4161776990994351.194122393370139728.3792954673409-120564.6080220011
64.9931747377179975.99688171360394236.48229059594851-115.5509621409682
7-1.41392846248888613.4977256988927525.47321630156819-26.39500283021502
8-10.8439170786969919.2774461671816523.94538338734709-5.650522971778156
CRAM-16 poles and residues (real and imaginary parts).

The CRAM-16 scaling constant is α0=2.124853710495224×1016\alpha_0 = 2.124853710495224 \times 10^{-16}.

Algorithm flow

Worked example: sequential decay chain

Consider a three-nuclide chain:

AλABλBC,A \xrightarrow{\lambda_A} B \xrightarrow{\lambda_B} C,

with λA=106s1\lambda_A = 10^{-6}\,\mathrm{s}^{-1}, λB=105s1\lambda_B = 10^{-5}\,\mathrm{s}^{-1}, and CC stable. The burnup matrix is

A=[λA00λAλB00λB0].\mathbf{A} = \begin{bmatrix} -\lambda_A & 0 & 0 \\ \lambda_A & -\lambda_B & 0 \\ 0 & \lambda_B & 0 \end{bmatrix}.

Starting from nA(0)=1015n_A(0) = 10^{15} atoms and nB(0)=nC(0)=0n_B(0) = n_C(0) = 0, the analytic solution after t=105st = 10^5\,\mathrm{s} is

  1. nA(t)=nA(0)eλAt=1015e0.19.0484×1014n_A(t) = n_A(0)\,e^{-\lambda_A t} = 10^{15}\,e^{-0.1} \approx 9.0484 \times 10^{14}.

  2. nB(t)=nA(0)λAλBλA(eλAteλBt)5.9662×1013n_B(t) = n_A(0)\,\frac{\lambda_A}{\lambda_B - \lambda_A}\, (e^{-\lambda_A t} - e^{-\lambda_B t}) \approx 5.9662 \times 10^{13}.

  3. nC(t)=nA(0)nA(t)nB(t)3.5501×1013n_C(t) = n_A(0) - n_A(t) - n_B(t) \approx 3.5501 \times 10^{13}.

Nucleide’s CRAM-48 result matches this analytic solution to better than one part in 10710^7 for nBn_B and one part in 10910^9 for nCn_C. This exact chain is exercised in crates/depletion/src/lib.rs as analytic_two_step_decay_cram48.

Loading chart…

Assumptions and limitations

  • One-group reaction rates: CRAM in Nucleide uses a single scalar rate per reaction channel. Multigroup fluxes must be collapsed externally.
  • Fixed cross sections over the step: A\mathbf{A} is treated as constant during tt.
  • Fission yields are single-energy: the yield set at the lowest incident neutron energy is used, matching OpenMC’s default.
  • Decay branching ratios: chains read from XML keep the file values verbatim; only programmatically built chains are renormalized (the largest branch is adjusted so the modes sum to exactly 1.0).
  • Stable nuclides have zero diagonal: they act as sinks in the chain.
  • CRAM order: order-16 is adequate for short, simple chains; order-48 is recommended for production burnup matrices.

Adjacent capabilities found in PyNE, OpenMC, and the literature that Nucleide does not implement:

  • Multi-step time integration: OpenMC ships predictor-corrector integrators (CECM, CELI, CF4, EPCRK4, and their SI variants) that recompute reaction rates between steps; Nucleide exposes a single constant-rate step.
  • Substepping: OpenMC’s CRAM solver can subdivide a step while reusing the LU factorizations; Nucleide has no substep parameter.
  • Transport-coupled depletion: OpenMC normalizes tally reaction rates to absolute rates from a power or source normalization; Nucleide assumes rates are already given in s1\mathrm{s}^{-1}.
  • Energy-dependent fission yields: OpenMC selects between constant, thermal, and thermal+fast yield modes; Nucleide uses the lowest-energy yield set.
  • Feed and removal terms: OpenMC adds transfer rates and external source vectors to the burnup matrix for MSR-style continuous processing.
  • Chain truncation: PyNE’s transmutagen-generated solver truncates the transmutation tree by density tolerance; Nucleide uses a fixed chain.
  • Krylov subspace methods: an alternative to CRAM for the Bateman equations; see Josey et al. (2017)josey-2017.