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_buildupwith a-coupled-photonquantity - 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")
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")
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")
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-photonis 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.