Skip to content

Coupled neutron and photon dose

A fast neutron source inside a shield generates secondary photons through inelastic scatter and neutron capture. For a complete dose estimate you need both the primary neutron dose and the secondary photon dose. There are two ways to get this:

  • Coupled Monte Carlo via compute_buildup with a -coupled-photon quantity - the most accurate option.
  • Analytical PK estimate via calculate_secondary_photon_dose - derives the secondary-gamma source per layer from neutron fluence and capture cross-sections, then transports the gammas to the detector. Faster and no MC required, but less accurate.

Coupled MC

Ask for the total. The library runs coupled neutron-photon transport, tallies both halves, and adds the sum to the result automatically:

import rad_point_kernel as rpk

iron = rpk.Material(composition={"Fe": 1.0}, density=7.874)
layers = [rpk.Layer(thickness=10, material=iron)]
source = rpk.Source(particle="neutron", energy=14.1e6)

results = rpk.compute_buildup(
    geometries=[layers],
    source=source,
    quantities=["dose-AP-total"],
)

# Pulsed DT shot: 1e16 neutrons per shot, dose lands in Sv/shot
r = results[0].scale(strength=1e16)
print(f"Total dose: {r.mc['dose-AP-total']} Sv/shot")
Total dose: 2939.878261633068 Sv/shot

The same shorthand works for any irradiation geometry: "dose-PA-total", "dose-RLAT-total", "dose-LLAT-total", "dose-ROT-total", "dose-ISO-total". It requires a neutron source.

Getting the neutron and photon contributions

The two component doses are still in the result if you need them - the shorthand expands to both halves under the hood, so nothing has to be re-run:

import rad_point_kernel as rpk

iron = rpk.Material(composition={"Fe": 1.0}, density=7.874)
layers = [rpk.Layer(thickness=10, material=iron)]
source = rpk.Source(particle="neutron", energy=14.1e6)

results = rpk.compute_buildup(
    geometries=[layers],
    source=source,
    quantities=["dose-AP-total"],
)
r = results[0].scale(strength=1e16)
print(f"Neutron dose:    {r.mc['dose-AP-neutron']} Sv/shot")
print(f"Secondary gamma: {r.mc['dose-AP-coupled-photon']} Sv/shot")
print(f"Total:           {r.mc['dose-AP-total']} Sv/shot")
Neutron dose:    2915.6182081672555 Sv/shot
Secondary gamma: 26.382975080000357 Sv/shot
Total:           2942.001183247256 Sv/shot

If you only ever want one of the components, you can also request it directly with "dose-AP-neutron" (neutron only) or "dose-AP-coupled-photon" (secondary photon only) - the latter still flips on coupled transport.

With a manual build-up factor

calculate_secondary_photon_dose accepts neutron_buildup as a BuildupModel. If you already have a neutron build-up factor from tabulated data or a prior run, pass it in:

import rad_point_kernel as rpk

iron = rpk.Material(composition={"Fe": 1.0}, density=7.874)
layers = [
    rpk.Layer(thickness=1000),
    rpk.Layer(thickness=10, material=iron),
]

source = rpk.Source(particle="neutron", energy=14.1e6)

B_neutron = 2.5
result = rpk.calculate_secondary_photon_dose(
    layers=layers,
    source=source,
    geometry="AP",
    neutron_buildup=rpk.BuildupModel.constant(B_neutron),
).scale(strength=1e16)
print(f"Neutron dose (B={B_neutron}): {result.neutron_dose} Sv/shot")
print(f"Secondary gamma dose:       {result.secondary_photon_dose} Sv/shot")
print(f"Total dose:                 {result.total_dose} Sv/shot")
Neutron dose (B=2.5): 0.2757132751376378 Sv/shot
Secondary gamma dose:       5.616708666195241 Sv/shot
Total dose:                 5.892421941332879 Sv/shot

Why the manual B is neutron-only

The secondary-gamma pathway is a derived quantity: neutron fluence reaches each material layer, capture and inelastic-scatter cross-sections determine how many secondary photons are born there, and the gammas are transported to the detector analytically. A user-supplied build-up factor only makes sense on the neutron leg - that is where "some of the scattered neutrons also reach this layer" is a first-class thing you tabulate. The secondary-photon leg has no analogous user-facing B input; its attenuation and geometry are built into the capture-gamma model itself. If you need to correct the secondary-photon side independently, prefer the Coupled MC path instead.

Notes

  • Coupled transport only makes sense for a neutron source; photon sources do not produce secondary neutrons in this tool.
  • dose-AP-coupled-photon is available alongside any irradiation geometry suffix: dose-PA-coupled-photon, dose-ISO-coupled-photon, etc.

Next: extracting build-up factors from MC

The compute_buildup call above tallies neutron and secondary-photon doses for one specific geometry. The same machinery can produce reusable build-up factors across a range of thicknesses, energies, or layer stacks - numbers you can plug back into calculate_flux or calculate_dose as BuildupModel.constant(B) on later runs without re-simulating. Calculate build-up with MC walks through that workflow.