Convert to multigroup transport free - #113
Conversation
First slice of the convert_to_multigroup(method="transport_free") feature (see #112). Deterministic per-material collapse of CE data against a narrow-resonance self-shielded flux phi = (1/E)/Sigma_t, no Monte Carlo / nparticles. Vector XS only (total/absorption/capture/fission); scatter matrices, the source-shaped + slowing-down weighting, and the convert_to_multigroup wiring come next.
…ollapse w(E) = 1/E + normalized source PDF (Normal/Discrete/Tabular/Mixture), so the fast groups are weighted by the actual DD/DT-Muir/TT source when provided; source remains optional (generic 1/E default).
Solve the infinite-medium slowing-down balance with real energy-transfer kernels from openmc.data (analytic elastic, discrete inelastic levels, tabulated continuum / (n,xn)) on a coarse lethargy grid via an exact high->low sweep, then self-shield on the fine total. Selectable via weighting='slowing_down' (NR remains the default). Empirically this does not beat NR on total XS, but the transfer kernels are the basis for the scatter matrix.
In the unresolved resonance range the pointwise data is the infinitely-dilute average, so phi=1/Sigma_t applies no self-shielding there. _apply_urr() restores the band structure from the URR probability tables (LSSF=1 factors) and computes the Bondarenko self-shielded effective total/absorption/capture, with sigma_0 the per-resonant-nuclide background from the rest of the material. On by default (use_urr=True). Empirically (VITAMIN-J-42, vs converged material_wise): tungsten total 2.54%->0.36%, absorption 2.63%->1.36%; non-URR materials unchanged.
…llapse weighting='ir' uses phi = w/[Sigma_t - sum_i (1-lambda_i) Sigma_s,i], with a per-nuclide lambda (default mass proxy 1-alpha, overridable via ir_lambda). lambda=1 reproduces the NR flux exactly (verified to machine zero). NON-DEFAULT: NR remains the default. Empirically (VITAMIN-J-42, vs converged material_wise) the parameter-free mass-proxy lambda does NOT improve on NR+URR and over-shields absorption (steel 1.9%->7.7%, Fe56 6.9%->14.3%): 1-alpha is the scatterer's slowing-down weight, whereas absorber self-shielding needs the Goldstein-Cohen lambda which is ~1 for narrow resolved resonances. A rigorous per-group lambda needs resonance-parameter fits and is sub-percent in fast spectra anyway. Kept as an option (overridable lambda) with this caveat; the recommended configuration is NR + URR probability tables.
…se_urr knobs) Self-shielding is not optional for a real material: the infinitely-dilute flux is never the more-accurate choice for transport, so neither the master self_shield toggle nor the use_urr sub-flag should be user-facing. Both are removed; resolved-resonance self-shielding (phi=w/Sigma_t) and unresolved probability-table self-shielding are now always applied. Keeps the public API knob-free (most-accurate-by-default), consistent with not exposing weight/scatter_order/correction. The raw dilute macroscopic xs remain available internally for diagnostics.
Weighting-flux investigation: what was tried, and why the method is just NRShort version: the method uses a 1/E narrow-resonance weight with always-on self-shielding, and the API has no weighting knob. Two alternative weightings ( All numbers below are mean |Δ| of the macroscopic cross section vs a converged
Intermediate resonance (
|
| reaction | material | NR+URR | +IR |
|---|---|---|---|
| total | tungsten | 0.36 % | 0.81 % |
| total | Fe-56 | 13.70 % | 11.38 % |
| absorption | steel | 1.91 % | 7.70 % |
| absorption | Fe-56 | 6.91 % | 14.31 % |
| absorption | tungsten | 1.36 % | 2.83 % |
It over-shields absorption. Root cause: the only λ computable without resonance parameters, 1−α, is the scatterer's slowing-down weight (≈0.07 for Fe), but absorber self-shielding needs the Goldstein-Cohen λ, which is ≈1 for the narrow resolved resonances of structural metals — so the proxy is backwards and removes ~93 % of Fe's scattering from the moderation denominator. A rigorous per-group λ needs resonance-parameter fits and would be sub-percent in a fast spectrum anyway. Removed: a user can't realistically supply a proper per-group λ and it can't be derived automatically, so the option had no usable path.
0-D slowing-down (weighting='slowing_down')
Solves the infinite-medium slowing-down balance Σ_t(E)φ(E) = S(E) + ∫ Σ_s(E′→E)φ(E′)dE′ on a coarse lethargy grid with real energy-transfer kernels from openmc.data (analytic elastic, discrete inelastic levels, tabulated continuum / (n,xn)), strictly down-scatter so an exact single high→low sweep, then self-shields on the fine total. It is the deterministic twin of the MC infinite_medium method.
It does not beat NR on total XS. NR is already ≤ ~1 % from the MC infinite-medium collapse for steel/Fe-56/concrete; the slowing-down flux lands ~1–2 % further off and the gap persists under grid refinement (Fe-56 vs infinite_medium: NR 1.13 %, SD plateaus at ~2.3 % over 40→300 lethargy pts/decade). Two reasons: (1) the total group XS is insensitive to the smooth flux shape — it only needs a 1/E-like spectrum, which NR supplies analytically; (2) the kernel's isotropic-CM elastic approximation carries its own error. It's also ~25× slower (~24 s vs ~1 s per material).
Its energy-transfer kernels are the scatter matrix — but that's out of scope here (random ray consumes the vector MGXS directly), so the option earned its removal too.
The actual levers (for context)
- Group fineness dominates — Fe-56 total error falls 22 % → 1.3 % from 8 → 975 groups, far more than any weighting choice. At fine fusion groups (CCFE-709, UKAEA-1102) transport-free (NR+URR) matches or beats
stochastic_slabon all four materials. - URR probability-table self-shielding is the one refinement that helped: tungsten total 2.54 % → 0.36 % (~7×), flipping it ahead of slab at every structure ≥ 25 groups. It's now always-on (part of self-shielding), not a knob.
So the method is NR weighting + always-on self-shielding (resolved + URR), exposed as a single knob-free call collapse_material(material, groups, source=None). ir and slowing_down were removed (commit 8108d5268) since neither improved the MGXS and neither had a usable path forward.
…s the method Neither improved the MGXS, and both are out of scope for a focused MGXS generator. IR with the mass-proxy lambda over-shields absorption, and a rigorous Goldstein-Cohen lambda can neither be supplied by users nor derived automatically. Slowing-down does not beat NR on total XS; its only value was the scatter-matrix transfer kernels, which we are not pursuing (random ray consumes the vector MGXS directly). Leaves a single deterministic, knob-free, noise-free generator: collapse_material(material, groups, source=None) -- 1/E (+optional source) narrow-resonance weighting with always-on self-shielding (resolved + URR). NR+URR output is byte-identical to before; module ~140 lines lighter.
scatter_matrix(material, groups, source=None) builds the P0 Sigma_s,g->g' [G_in,G_out] (OpenMC ordering) needed to actually feed a P0 solver such as random ray -- completing the deterministic library alongside the vector XS. Kernels (no Monte Carlo): elastic with the real CM angular distribution (E_out=E*(A^2+2A mu+1)/(A+1)^2 folded over f(mu)); discrete inelastic levels spread over their lab energy range [base +/- amp]; continuum / (n,xn) via unit-base interpolation of the secondary-energy distributions, summed over all neutron products with multiplicity (yield_). A per-group panel sub-grid resolves the elastic in-group/down-scatter split where pointwise data is sparse, and upscatter artifacts are folded into the diagonal. Validated vs cached MC scatter matrices (P0): tungsten ties stochastic_slab at fine fusion groups (CCFE-709: 10.8% vs 10.6% element-wise); steel/Fe56 ~1.4-1.5x slab; row-sums competitive. Same NR+URR weighting flux as collapse_material.
Deterministic scatter matrix added (commit f96b34c) — and how it was made accurateRandom ray rebuilds its scattering source every sweep from a group-to-group matrix Σs,g→g′ ( Kernels (all deterministic, from
|
| material | VITAMIN-J-42 det / slab | CCFE-709 (fine) det / slab |
|---|---|---|
| tungsten | 9.6% / 2.5% | 10.8% / 10.6% (ties slab) |
| steel | 4.4% / 3.1% | — |
| Fe-56 | 7.5% / 5.1% | — |
The decisive fix for tungsten was the panel sub-grid: sparse groups previously held only their lower edge, sending all elastic into the group below and collapsing the diagonal (51% → 9.6%). At the fine fusion structures actually used (CCFE-709), tungsten now ties stochastic_slab — both near the ~10% MC element-noise floor. The element-wise metric is harsh (it weights small MC-noisy off-diagonals); what matters for the RR answer is the scattering source Σ_g′ Σ_s φ, where row-sums and dominant transfers dominate, and row-sums are competitive across the board (steel ties slab).
In progress (overnight)
- Expanding the test set to concrete and CuCrZr (ITER-grade Cu-Cr-Zr heat sink) for more confidence across material types.
- Researching + trying further accuracy levers for the resonant structural metals (steel/Fe-56), notably transport correction (TC-P0) for the forward-peaked elastic, scatter-matrix resonance self-shielding, and finer incident-energy quadrature.
Results and what worked / didn't will be posted here as they land. Recommended config remains NR weighting + always-on self-shielding; the scatter matrix uses the same flux.
Overnight: superior scatter matrix + 10-material confidence studyTest set expanded to 10 materials spanning the fusion range: tungsten, steel, Fe-56, CuCrZr, Zircaloy, SiC, Li₄SiO₄ (breeder), concrete, H₂O, helium (5 MPa/500 °C). Each validated on both the vector total XS and the P0 scatter matrix vs Vector total XS vs material_wise (fine groups, CCFE-709)Transport-free is excellent across the whole range:
Sub-0.5% for 8 of 10; only the two resonance-heavy metals (W, Fe-56) reach ~2.5%. (Coarse VJ-42: same picture except Fe-56 14.6% — the known coarse-group spatial-spectrum effect.) Scatter matrix
Weighting flux: IR / slowing-down checked for the scatter matrix (per request)Neither beats NR. IR marginally helps pure Fe-56 (source 12.9→10.8%) but hurts steel/tungsten; slowing-down is worse for steel/tungsten. NR remains the best weighting for the scatter matrix too — same verdict as for the vector XS. Transport correction (TC-P0) — implementedResearch (2 workflows) identified TC-P0 as the #1 physical lever for a P0 random-ray library, and that random ray expects the correction applied in the library (it does none itself, verified in Honest open items
|
scatter_matrix(..., return_p1=True) also returns the P1 outscatter moment Sigma_s1,g = sum_g' mu_lab(g->g') * sigma_s0(g->g'), accumulated from the real CM elastic angular distribution. A transport-corrected (TC-P0) library for a P0 solver such as random ray is then sigma_tr = sigma_t - Sigma_s1 with the in-group diagonal reduced by the same Sigma_s1 (random ray expects the correction in the library, not the solver; negative diagonals are expected and handled by its diagonal stabilization). Verified Sigma_s1>=0, sigma_tr<=sigma_t; the correction is large for forward-peaked elastic (tungsten ~50% of sigma_t at 14 MeV). Default behaviour unchanged (return_p1=False).
10-material validation: transport-free vs stochastic_slab (both vs material_wise)Expanded the test set to 10 materials spanning the fusion range — tungsten, steel, Fe-56, CuCrZr, Zircaloy, SiC, Li₄SiO₄ (breeder), concrete, H₂O, helium (5 MPa/500 °C) — scored on both the vector total XS and the P0 scatter matrix, at coarse (VITAMIN-J-42), mid-fine (XMAS-172) and fine (CCFE-709) groups. Robust metrics: total XS, scatter row-sum (=scatter XS), and a mean-lethargy-gain shape metric (an integral that averages out the per-element MC reference noise that makes the raw element-wise / source metrics unreliable at fine groups). Fine groups (CCFE-709), mean |Δ| vs material_wise — det / slab
Total XS: transport-free ties/beats slab on 7/10 at fine groups (4/10 at coarse — group fineness helps, as expected). It wins outright on helium and Li₄SiO₄ where stochastic_slab struggles (dilute gas / breeder). Scatter shape: competitive/winning for every metal, ceramic, breeder and coolant; the only failures are the hydrogenous H₂O and concrete (shape 2–3 lethargy units off). That is the missing thermal scattering (free-gas / S(α,β) for hydrogen) — not fixable by group fineness, and out of scope for a fast structural-metal library but real for moderators. What else was tried
Honest bottom lineFor the fusion-relevant materials (structural metals, ceramics, breeder, coolant) transport-free is as good as or better than stochastic_slab on both vector XS and the scatter matrix at fine groups, and is noise-free/deterministic. The documented limitation is hydrogenous moderators (H₂O, concrete), whose scatter matrices need a thermal scattering kernel. Next: a thermal kernel for moderators, and the decisive downstream random-ray-vs-CE benchmark. |
…trix) scatter_matrix(..., thermal=True) replaces the static target-at-rest elastic kernel with a free-gas (ideal-gas) energy-transfer kernel below 5 eV for light nuclides (A<=20), capturing thermal up-scatter and broadening that the static kernel misses. _freegas_gf() integrates over the target Maxwellian (isotropic CM); verified against analytic Wigner-Wilkins for A=1 to ~1-2%. Real thermal up-scatter is preserved (the upscatter-to-diagonal fold is skipped below 5 eV). Cuts the H2O/concrete scatter-matrix shape error ~2-3x (mean lethargy-gain vs material_wise: H2O 3.07->1.43, concrete 2.12->0.75); neutral for metals/heavy nuclides (A>20, unchanged). Uses free-gas (not bound S(alpha,beta)) -- matches OpenMC's default thermal treatment for materials without an S(a,b) table; a residual remains vs MC for hydrogenous moderators.
Free-gas thermal scattering kernel — tried and re-tested (commit 7b7164a)The one remaining scatter-matrix weakness was the hydrogenous moderators (H₂O, concrete): their scatter shape was 2–3 lethargy units off material_wise because the kernel treated the target as at rest (no thermal motion / up-scatter). Added a free-gas (ideal-gas) thermal kernel: Effect at fine groups (CCFE-709), scatter matrix vs material_wise
The thermal kernel cuts the hydrogenous scattering-source error 5–10× and the shape 2–3×, and is neutral for metals (the main use case). Helium and Li₄SiO₄ now beat stochastic_slab outright. Honest residualH₂O/concrete shape is still ~1.4 / 0.75 lethargy units vs slab's ~0.04 / 0.11. The free-gas kernel is correct (matches Wigner-Wilkins), so the residual is the harder full-thermalization match — bound S(α,β) for hydrogen in water/concrete (vs the free-gas the MC reference uses by default), plus per-fine-point (not per-group) thermal evaluation. That's the next refinement for moderators; for a fast fusion structural/ceramic/breeder/coolant library it's already in good shape. Overall 10-material verdict (CCFE-709, fine groups)
|
The free-gas thermal kernel now activates below 400*kT (= OpenMC's settings.free_gas_threshold default, ~10 eV at 294 K) instead of a hardcoded 5 eV, and the upscatter-fold uses the same cutoff. Temperature-scaled and consistent with the MC reference. When wired into convert_to_multigroup this should read settings.free_gas_threshold from the model rather than the 400 default. (Small numerical effect, since 5-10 eV is already well above thermal, but it is the correct, temperature-scaled value.)
… deltas The elastic kernel deposited one delta per angular-grid mu point. For heavy nuclides (E_out ~ E, near-diagonal) this is fine, but for hydrogen the wide [0,E] down-scatter put every mu~-1 point (E_out~0) into the LOWEST group instead of spreading smoothly down the slowing-down range -- a ~14% spurious dump at the grid floor for fast incoming groups. Now the outgoing energy (monotonic in mu) is spread across outgoing groups via the angular CDF, integrated over group edges. Huge improvement for hydrogenous materials (CCFE-709 scatter-shape, mean lethargy-gain vs material_wise): H2O 1.37 -> 0.016, concrete 0.72 -> 0.035 -- both now BEAT stochastic_slab (0.041, 0.106). Metals unchanged (already near-diagonal). The P1/TC-P0 moment is spread consistently (row-sum unchanged).
Elastic scatter binning fixed via angular CDF — the hydrogenous-shape residual was a binning bug, not thermal physics (commits 90af724, 103bd8e)My previous comment blamed the H₂O/concrete scatter-shape residual on missing bound S(α,β). That diagnosis was wrong. Localising the H₂O error by energy showed the thermal region was already excellent (mean-lethargy-gain |Δ| 0.03 vs material_wise, up-scatter mass matched to 0.1%) — the whole residual sat in the fast/epithermal elastic range. Root cause: the elastic kernel deposited one delta per angular-grid μ-point. For heavy nuclides E_out ≈ E (near-diagonal), so this is harmless — which is why every metal looked fine and the bug hid for months. But for hydrogen the down-scatter spans the full [0, E]; every μ ≈ −1 point maps to E_out ≈ 0 and piled into the lowest energy group. A 977 keV incoming group dumped 14 % of its scatter at the grid floor instead of spreading smoothly down the slowing-down range. Fix (103bd8e): E_out is monotonic in μ, so the angular distribution is now spread smoothly across outgoing groups via its CDF, integrated over the group edges — no deltas. The P1/TC-P0 moment is spread consistently (row-sum unchanged, so the transport correction is unaffected). Effect — scatter shape (mean lethargy gain) vs material_wise, CCFE-709
H₂O and concrete now beat stochastic_slab on scatter shape (and the 14 % spurious dump is gone, 0 %). The earlier free-gas thermal kernel still does its job for genuine thermal up-scatter; the threshold for it was also corrected to 400·kT (OpenMC's Full 10-material status — CCFE-709 (transport-free
|
| material | TOTAL d/slab | scatter ROWSUM d/slab | SHAPE d/slab |
|---|---|---|---|
| tungsten | 1.96 / 2.56 | 3.60 / 2.36 | 0.004 / 0.006 |
| steel | 0.57 / 0.48 | 0.75 / 0.56 | 0.008 / 0.008 |
| Fe-56 | 3.31 / 1.39 | 3.40 / 1.45 | 0.011 / 0.010 |
| CuCrZr | 0.86 / 1.02 | 1.34 / 1.12 | 0.017 / 0.017 |
| Zircaloy | 0.79 / 0.91 | 1.02 / 0.99 | 0.014 / 0.014 |
| SiC | 0.12 / 0.06 | 0.40 / 0.06 | 0.023 / 0.018 |
| Li₄SiO₄ | 0.06 / 0.42 | 0.39 / 3.26 | 0.041 / 0.218 |
| concrete | 0.05 / 0.09 | 0.29 / 0.10 | 0.035 / 0.106 |
| H₂O | 0.02 / 0.05 | 0.17 / 0.05 | 0.016 / 0.041 |
| helium | 0.19 / 2.10 | 0.17 / 9.66 | 0.117 / 0.529 |
(All errors in %, except SHAPE in lethargy units. Bold = transport-free wins.)
Where it stands
- Scatter-matrix SHAPE: solved. With the binning fix, transport-free ties or beats slab on shape for all 10 materials — the moderators were the last holdout and now lead.
- Vector TOTAL XS: transport-free ties/beats slab 7/10.
- Remaining gaps are XS magnitude (TOTAL, scatter ROWSUM) on the deep resonant materials — Fe-56 above all (3.3 % vs slab 1.4 %), steel/SiC marginally. These are not a kernel issue: they are the spatial-spectrum limit. In this deliberately harsh 10-shell deep stack, slab's artificial mixed-material weighting flux happens to resemble the degraded local spectrum of a deep material better than any single near-source weighting can.
Weighting flux re-checked (again)
Confirmed the magnitude gaps are not closeable by changing the weighting flux: slowing-down weighting is worse than NR for exactly these materials (Fe-56 ROWSUM 3.6 % SD vs 3.4 % NR; tungsten 4.2 % vs 3.6 %), and IR was checked earlier with the same verdict. NR remains the best single weighting for both vector and scatter data. Closing the deep-resonant magnitude gap would require depth-/spectrum-aware data (multiple background σ₀ tiers or a degraded reference spectrum), which trades away the geometry-independence that makes this transport-free and instant.
Honest open items
- Deep resonant magnitude (Fe-56) is the one place slab still leads on a deep stack; for representative (non-deep-stack) spectra transport-free's per-material vector XS is sub-0.5 %.
- The decisive end-to-end test is a downstream random-ray-vs-CE shielding run — that, not the deep-stack collapse metric, is what determines whether transport-free is good enough to feed RR.
Are we fooling ourselves? Monte-Carlo convergence check of the benchmark
Setup. Both references already run 100 active batches: Q1 — does
|
| material | TOTAL 1× → 10× | ROWSUM 1× → 10× |
|---|---|---|
| tungsten | 2.56 → 2.57 | 2.36 → 2.34 |
| steel | 0.48 → 0.48 | 0.56 → 0.51 |
| Fe-56 | 1.39 → 1.41 | 1.45 → 1.47 |
| CuCrZr | 1.02 → 1.02 | 1.12 → 1.05 |
| Zircaloy | 0.91 → 0.91 | 0.99 → 1.00 |
| SiC | 0.06 → 0.05 | 0.06 → 0.06 |
| Li₄SiO₄ | 0.42 → 0.06 | 3.26 → 0.07 |
| concrete | 0.09 → 0.07 | 0.10 → 0.07 |
| H₂O | 0.05 → 0.03 | 0.05 → 0.03 |
| helium | 0.39 → 0.04 | 10.70 → 2.30 |
For the dense/resonant metals where slab beats us (W, steel, Fe-56, CuCrZr, Zr) the error does NOT move with 10× particles — it is fully-converged systematic bias (the random-slab spectrum ≠ the deep-stack local spectrum), not noise. So the worry is unfounded there: more particles will not let slab pull ahead. Where slab was noise-limited is the low-density materials (Li₄SiO₄, helium): there its error collapses with 10× (Li₄SiO₄ row-sum 3.26 → 0.07). So our earlier "transport-free beats slab on Li₄SiO₄/He row-sum" was partly beating an under-converged slab — with a converged slab, slab is excellent on those too (helium row-sum is the one place we still lead, 0.17 vs 2.30).
Q2 — the bigger finding: the material_wise truth is itself noisy
Two independent material_wise seeds (same 4M histories) disagree by:
| material | TOTAL seed1-vs-seed2 | ROWSUM seed1-vs-seed2 |
|---|---|---|
| Fe-56 | 2.82 | 2.45 |
| Zircaloy | 2.49 | 2.18 |
| SiC | 2.43 | 2.88 |
| CuCrZr | 2.13 | 1.83 |
| tungsten | 1.67 | 1.15 |
| steel | 1.14 | 0.95 |
| Li₄SiO₄ | 1.93 | 1.72 |
| helium | 1.42 | 1.72 |
| concrete | 0.03 | 0.20 |
| H₂O | 0.01 | 0.02 |
The reference itself carries 1–3 % noise for the resonant metals (the deep shells get few tally scores). That means the fine-group per-material "errors" we quote for Fe-56/W/CuCrZr/Zr/SiC — for both transport-free and slab — are being measured against a ±2 % ruler. The transport-free-vs-slab gap on Fe-56 (3.3 vs 1.4) is partly comparing noise; both sit within the truth's uncertainty band.
Conclusions
- The benchmark is sound for the materials with a clean ruler. H₂O and concrete have ~0.01–0.2 % reference noise — there transport-free wins cleanly and unambiguously (total 0.02/0.05, and it now leads on scatter shape after the elastic CDF fix).
- slab is not under-converged where it matters — its lead on the resonant metals is real bias, not noise; 10× particles changes nothing there. We were not fooling ourselves in that direction.
- But the resonant-metal comparison is reference-noise-limited. To cleanly resolve sub-2 % differences (Fe-56, W, CuCrZr, Zr) we need a much more converged
material_wise(≈10–100× histories), or — better — to stop using the deep-stack collapse metric as the arbiter and run the downstream random-ray-vs-CE shielding calculation, which integrates over the spectrum and is the actual use case.
Next: a lit-review-guided self-shielding improvement to the scatter matrix (SCALE/AMPX Bondarenko f-factor on the elastic matrix), reported separately.
The scatter matrix used the dilute (infinite-dilution) elastic cross section in the unresolved resonance range, while the vector total was already URR-corrected. That left the scatter row-sum too high across the URR for nuclides with probability tables. Apply the same probability-table band average to the elastic channel (table column 2), giving a per-nuclide micro elastic self-shielding factor f_el(E)=<sigma_el>/sigma_el,smooth, and multiply the elastic XS by it before building the transfer matrix -- the SCALE/AMPX approach of self-shielding the 2D elastic matrix via a Bondarenko f-factor. Effect (CCFE-709 scatter row-sum vs material_wise): tungsten 3.60 -> 1.95 (now beats stochastic_slab 2.34), Zircaloy 1.02 -> 0.94 (beats slab 1.00). Materials whose nuclides have no URR table (steel/Fe-56/SiC/Li4SiO4/H2O/concrete/He) are unchanged -- they are fully resolved, already self-shielded by phi=1/Sigma_t.
Improving total / scatter row-sum: lit review + first implemented gain (commit ddee0a9)A 6-angle, 21-source, adversarially-verified literature review of transport-free MG total/scatter generation for resonant structural materials, plus a code review, identified the techniques below. One is now implemented; the rest are a prioritized roadmap. Implemented now — Bondarenko f-factor on the elastic matrix (URR)The code review found the scatter matrix used the dilute elastic XS in the unresolved range while the vector total was already URR-shielded — an inconsistency. The lit review confirmed this is exactly what SCALE/AMPX corrects:
I apply the probability-table band average to the elastic channel (a per-nuclide f_el(E)=⟨σ_el⟩/σ_el,dilute) before building the transfer matrix. CCFE-709 scatter row-sum vs material_wise:
Tungsten and Zircaloy now beat slab on row-sum; nothing regresses. Important caveat — the materials you named have no URRSteel (Fe/Cr/Ni), Fe-56, and SiC (Si/C) have no unresolved range at all — they are fully resolved, so φ=1/Σ_t already self-shields them directly from the pointwise data. The URR f-factor does not touch them. Combined with the convergence check above (Fe-56 reference noise ≈ 2.8 %), their residual is currently below the noise of the material_wise ruler — we cannot reliably measure an improvement to steel/Fe-56/SiC without a much more converged reference (or the downstream RR-vs-CE test). Roadmap for the resolved-range residual (verified techniques, in priority order)
Honest takeawayThe scatter-matrix shape is solved (elastic CDF fix) and now the URR elastic magnitude is self-shielded (W, Zr fixed). The remaining total/row-sum gaps are on the fully-resolved resonant metals (steel, Fe-56, SiC), where (a) the proper fix is a σ₀-parameterised resolved-range f-factor or IR/compound-flux weighting, and (b) the current benchmark can't even measure sub-2 % gains there. The most informative next step is a converged reference or the downstream random-ray-vs-CE run, then lever (1)/(2). |
Consolidated scatter-matrix comparison (both fixes in) + correction to the noise figuresDefinitive table at CCFE-709, 10-shell deep stack, transport-free with both fixes (elastic CDF-spread Scatter row-sum (scatter XS magnitude), % error vs material_wise
Scatter shape (mean lethargy gain, |Δ| vs material_wise — lower better)
Verdict
Correction to the convergence-check comment aboveThat earlier comment quoted |
Principled fix attempted: exact 0-D slowing-down weighting flux — definitive negative resultThe roadmap's top within-material lever was to replace the narrow-resonance flux (φ=1/Σ_t) with the exact 0-D infinite-medium slowing-down flux, which captures wide/intermediate-resonance scattering with no Goldstein-Cohen λ. The earlier attempt at this was crippled (it solved the balance on a coarse 40-bin/decade grid, then divided a smooth source by the fine Σ_t — i.e. it was still essentially NR). This time it was done properly:
solved by an exact high→low sweep on the full pointwise resonance grid (52k–323k points), so the scattering source carries φ's own resonance dips self-consistently. Fast (0.1–8 s/material). It is implemented correctly — the wide-resonance physics IS capturedAt Fe-56's scattering resonances the solved flux dips shallower than NR's 1/Σ_t (exactly the wide-resonance effect — neutrons scatter within the resonance and replenish the flux):
(The two fluxes differ by >100 % in places — this is a genuinely different, correctly-solved flux, not a null.) But it does not move the group-collapsed cross sectionCCFE-709, vs material_wise:
The change is ≤ 0.02 % (and if anything marginally worse). Reason: at fine (5 %) groups the collapse ∫φσ/∫φ is dominated by the 1/Σ_t self-shielding factor that NR and SD share; the shallower-dip correction is a small, locally-cancelling effect on the numerator. Conclusion — the weighting-flux avenue is now closedNR ≈ crude IR (≈ +0.3 %) ≈ exact 0-D slowing-down flux (≈ 0). The within-material weighting flux is conclusively not the lever for the resonant-metal gap. Combined with the earlier evidence (per-material-sphere Fe-56 already ~2.7 %), the remaining Fe-56 deficit is the spatial-spectrum — the deep-stack local flux is softer/more degraded than any 0-D infinite-medium flux, and slab's random-slab geometry happens to reproduce that better. No assumed single weighting (NR/IR/SD) can capture a geometry-dependent local spectrum. The only routes left for Fe-56's magnitude are therefore (a) finer groups (drives the collapse toward weighting-independence) or (b) spectrum/σ₀-aware data (multiple weightings / background tiers) — both trade away simplicity/geometry-independence. The decisive arbiter remains the downstream random-ray-vs-CE run, not the deep-stack collapse metric. The SD-flux solver is kept in the prototype for the record but is not added to the module — NR stays the verified-best weighting. |
Set-to-zero & re-solve; validated best on smooth (0.74% vs diamond 0.89, step 1.17), positive flux. BUT on the resonant stack the set-to-zero clamp accumulates more error than step (Fe-56 2.06 vs step 1.08) -- many resonance negativities. Conclusion: no spherical scheme beats the robust 1D-slab transport (#114, Fe-56 0.60) on deep resonant materials; spherical only helps near-source. Recommend the #113+#114+NR-near-source hybrid. See FINDING_realgeom.md.
Cross-talk benchmarks: when is NR+URR sufficient?Built controlled 2-material adjacency benchmarks (concentric spheres, 14 MeV point source) to test whether the placement-BLIND NR+URR method here matches (Single-seed MC references at moderate statistics; estimated noise ~2% for the deep/resonant tallies — relevant below.) W │ H₂O — resonant absorber + moderator
NR+URR is sufficient for both, in both placements. W behind 12 cm of water collapses to ~1% — at/below the MC noise floor (essentially exact), and no worse than W at the front. Moderating the spectrum does not break NR (water is smooth; it shifts the spectrum but carves no resonance dips at W's energies). steel │ Fe-56 — two resonant metals (overlapping Fe resonances)
NR has a real ~3% gap on Fe-56 that transport closes to ~0.8%. Key (and corrective) finding: the Fe-56 gap is NOT inter-material cross-talkFe-56's NR error is ~3% whether it sits behind steel or at the front, and Bottom line for this method
Caveat for the end use (random ray)
|
…nchmark Add method="transport_free" to Model.convert_to_multigroup, dispatching to a new _generate_transport_free_mgxs that deterministically builds the MGXS library from the openmc.mgxs.transport_free module (NR+URR self-shielded vector XS + deterministic P0 scatter matrix; optional TC-P0 via correction="P0"). No Monte Carlo, no transport solve; positive total XS in every group, so it feeds random ray with no fixups. examples/transport_free_random_ray/ adds an end-to-end RR-vs-CE fusion-shield benchmark (neutronics-workshop tokamak materials: 14.1 MeV plasma source -> W -> steel -> Li -> concrete) comparing random ray fed by transport_free vs stochastic_slab against a continuous-energy reference. Finding: at fine fusion groups (CCFE-709) transport_free matches stochastic_slab accuracy (parity, within a few %) and beats it at coarse groups; transport_free is strictly more robust (deterministic, noise-free, valid in every group, while slab needed a negative-XS fixup to run in random ray).
Wired
|
| deep-attenuation error vs CE | deepest-region (concrete) spectral error | |
|---|---|---|
| VITAMIN-J-42 (40 grp) | slab 234% · tf 41% | slab 93% · tf 65% |
| CCFE-709 (650 grp) | slab 32% · tf 36% | slab 36% · tf 35% |
At coarse groups transport_free is far better deep (slab's coarse XS badly mis-predict the
flux suppression). At fine fusion groups the two converge to near-parity — flux-weighted
spectral error within a few % in every region (slab a hair better at the first wall,
transport_free a hair better at the deepest point). This is exactly the collapse-metric finding:
finer groups make within-group weighting nearly irrelevant, so the methods agree.
In the physically-relevant (high-flux) energy range all three — CE, RR-slab, RR-tf — agree well;
the visible disagreement is the negligible deep-thermal tail (slab = MC noise, tf = smooth).
Bottom line
For the random-ray workflow, transport_free matches stochastic_slab's accuracy at the fine
groups used for fusion shielding, beats it at coarse groups, and is strictly more robust
(deterministic, noise-free, valid in every group — no negative-XS fixup needed).
Caveat: the RR solve here is moderately resolved (a few flat source regions per layer);
absolute errors vs CE (~20–40% flux-weighted at CCFE-709) are dominated by that and are common
to both methods. A higher-resolution RR solve (more source regions, linear source, more rays)
would sharpen the absolute verdict; the relative method comparison is unaffected.


Experimental branch for transport-free multigroup cross-section generation — a deterministic
convert_to_multigroup(method="transport_free")that collapses continuous-energy data against an assumed weighting flux, with no Monte Carlo and nonparticles. Tracking issue: #112.Target use case: feeding OpenMC's random-ray solver for fusion deep-penetration shielding (fine group structures, neutron-dominated). It aims to sit between the existing MC methods — more reproducible/noise-free than
stochastic_slab, far cheaper thanmaterial_wise.What's here
openmc/mgxs/transport_free.py—collapse_material(material, groups, ...)does a per-material collapse of CE data (openmc.data, ENDF/B-8.1) to vector cross sections (total / absorption / capture / fission). Each material is collapsed directly against its own macroscopic flux; per-nuclide multigroup data are never combined (they are flux-weighted averages and do not add cleanly — see #112, principle 7).Self-shielding is always applied — resolved resonances via
φ = w(E)/Σ_tand the unresolved range via Bondarenko probability tables. It is not optional (a real material is never at infinite dilution), so the API is knob-free — a single deterministic call, no accuracy options:source(optional) folds the actual source spectrum (muir/Discrete/Tabular/Mixture) into the 1/E weight when available; everything else is automatic. A 1/E narrow-resonance weight is used because the cross-section values are insensitive to the smooth flux shape — richer weightings were tried and gave no benefit (below).Validated results
Reference (truth) = high-statistics
material_wise; baseline confirmed converged (MC noise floor < 0.05 % total / < 0.3 % absorption at 40 k particles × 2 seeds, so reported deltas are real physics, not noise). Geometry: W → steel → Fe-56 → concrete shells, 14.06 MeV Muir source.URR self-shielding is a decisive win for tungsten (the hardest material). Total-XS mean |Δ| vs truth:
Across a coarse→fine sweep, NR+URR beats
stochastic_slabon tungsten total XS at every structure from 25 groups up.At fine fusion groups (CCFE-709), NR+URR wins or ties every material vs
stochastic_slab(total XS mean |Δ|): tungsten 1.58 % vs 2.44 %, steel 0.30 % vs 0.34 %, Fe-56 1.96 % vs 1.95 % (tie), concrete 0.07 % vs 0.07 % (tie) — and transport-free is noise-free wherestochastic_slableaves empty/spiky groups.Group fineness is the dominant lever, not the weighting: e.g. Fe-56 total error falls 13.7 % → ~2 % going 42 → 650 groups, because narrow groups make the within-group weighting nearly irrelevant.
Tried and removed (neither improved the MGXS):
Both were implemented, benchmarked, then removed (details in the PR comments) so the generator stays a single knob-free method.
Speed: ~45 s for all four materials at any structure (dominated by HDF5 I/O; the collapse math is sub-second), flat in group count, deterministic — versus ~6 min per MC reference run.
Not yet done
convert_to_multigroup(method="transport_free")dispatch wiring (the collapse core exists; theModelmethod is next).