Skip to content

reactions

Fusion reactions and their data.

AllReactions = tokamak_neutron_source.reactions.Reactions | tokamak_neutron_source.reactions.AneutronicReactions module-attribute

Represent a PEP 604 union type

E.g. for int | str

BALLABIO_DD_NEUTRON = BallabioEnergySpectrum(energy_0=2449.5, omega_0=82.542, energy_shift_coeffs=BallabioCoefficients(a1=4.69515, a2=-0.040729, a3=0.47, a4=0.81844), width_correction_coeffs=BallabioCoefficients(a1=0.0017013, a2=0.16888, a3=0.49, a4=0.0007946)) module-attribute

Ballabio et al. fit data for relativistic fusion reaction neutron energy Gaussian spectra.

BALLABIO_DT_NEUTRON = BallabioEnergySpectrum(energy_0=14021.0, omega_0=177.259, energy_shift_coeffs=BallabioCoefficients(a1=5.30509, a2=0.0024736, a3=1.84, a4=1.3818), width_correction_coeffs=BallabioCoefficients(a1=0.00051068, a2=0.0076223, a3=1.78, a4=8.7691e-05)) module-attribute

Ballabio et al. fit data for relativistic fusion reaction neutron energy Gaussian spectra.

BOSCH_HALE_DD_3HEN = BoschHaleCoefficients(name='D + D --> 3He + n', t_min=0.2, t_max=100.0, bg=31.397, mrc2=937814.0, c=array([ 5.43360e-12, 5.85778e-03, 7.68222e-03, 0.00000e+00,-2.96400e-06, 0.00000e+00, 0.00000e+00])) module-attribute

Bosch-Hale parameterisation dataclass.

H.-S. Bosch and G.M. Hale 1992 Nucl. Fusion 32 611 DOI 10.1088/0029-5515/32/4/I07

BOSCH_HALE_DD_TP = BoschHaleCoefficients(name='D + D --> T + p', t_min=0.2, t_max=100.0, bg=31.397, mrc2=937814.0, c=array([5.65718e-12, 3.41267e-03, 1.99167e-03, 0.00000e+00, 1.05060e-05,0.00000e+00, 0.00000e+00])) module-attribute

Bosch-Hale parameterisation dataclass.

H.-S. Bosch and G.M. Hale 1992 Nucl. Fusion 32 611 DOI 10.1088/0029-5515/32/4/I07

BOSCH_HALE_DT_4HEN = BoschHaleCoefficients(name='D + T --> 4He + n', t_min=0.2, t_max=100.0, bg=34.3827, mrc2=1124656.0, c=array([ 1.17302e-09, 1.51361e-02, 7.51886e-02, 4.60643e-03,1.35000e-02, -1.06750e-04, 1.36600e-05])) module-attribute

Bosch-Hale parameterisation dataclass.

H.-S. Bosch and G.M. Hale 1992 Nucl. Fusion 32 611 DOI 10.1088/0029-5515/32/4/I07

E_DD_HE3N_FUSION = 5.237367559215132e-13 module-attribute

Convert a string or number to a floating point number, if possible.

E_DD_NEUTRON = 3.924425728571561e-13 module-attribute

Convert a string or number to a floating point number, if possible.

E_DD_TP_FUSION = 6.461016407480568e-13 module-attribute

Convert a string or number to a floating point number, if possible.

E_DHE3_FUSION = 2.940668400408501e-12 module-attribute

Convert a string or number to a floating point number, if possible.

E_DT_FUSION = 2.8183035155819573e-12 module-attribute

Convert a string or number to a floating point number, if possible.

E_DT_NEUTRON = 2.250912784396904e-12 module-attribute

Convert a string or number to a floating point number, if possible.

E_TT_FUSION = 1.8157845541890245e-12 module-attribute

Convert a string or number to a floating point number, if possible.

E_TT_NEUTRON = 7.546109313264398e-13 module-attribute

Convert a string or number to a floating point number, if possible.

ReactionData

Reaction dataclass.

Source code in tokamak_neutron_source/reactions.py
@dataclass(frozen=True)
class ReactionData:
    """Reaction dataclass."""

    label: str
    total_energy: float
    num_neutrons: int
    cross_section: ReactionCrossSection
    bosch_hale_coefficients: BoschHaleCoefficients | None
    ballabio_spectrum: BallabioEnergySpectrum | None

ReactionEnumMixin

Provides convenient accessors to the underlying ReactionData.

Source code in tokamak_neutron_source/reactions.py
class ReactionEnumMixin:
    """Provides convenient accessors to the underlying ReactionData."""

    @property
    def data(self) -> ReactionData:  # noqa: D102
        return self.value

    @property
    def label(self) -> str:  # noqa: D102
        return self.value.label

    @property
    def total_energy(self) -> float:  # noqa: D102
        return self.value.total_energy

    @property
    def num_neutrons(self) -> int:  # noqa: D102
        return self.value.num_neutrons

    @property
    def cross_section(self) -> ReactionCrossSection:  # noqa: D102
        return self.value.cross_section

    @property
    def bosch_hale_coefficients(self) -> BoschHaleCoefficients | None:  # noqa: D102
        return self.value.bosch_hale_coefficients

    @property
    def ballabio_spectrum(self) -> BallabioEnergySpectrum | None:  # noqa: D102
        return self.value.ballabio_spectrum

ballabio_spectrum property

bosch_hale_coefficients property

cross_section property

data property

label property

num_neutrons property

total_energy property

Reactions

Bases: tokamak_neutron_source.reactions.ReactionEnumMixin, enum.Enum

Neutronic reaction channels.

Source code in tokamak_neutron_source/reactions.py
class Reactions(ReactionEnumMixin, Enum):
    """Neutronic reaction channels."""

    D_T = ReactionData(
        label="D + T → ⁴He + n",
        total_energy=E_DT_FUSION,
        num_neutrons=1,
        cross_section=DT_XS,
        bosch_hale_coefficients=BOSCH_HALE_DT_4HEN,
        ballabio_spectrum=BALLABIO_DT_NEUTRON,
    )
    D_D = ReactionData(
        label="D + D → ³He + n",
        total_energy=E_DD_HE3N_FUSION,
        num_neutrons=1,
        cross_section=DD_HE3N_XS,
        bosch_hale_coefficients=BOSCH_HALE_DD_3HEN,
        ballabio_spectrum=BALLABIO_DD_NEUTRON,
    )
    T_T = ReactionData(
        label="T + T → ⁴He + 2n",
        total_energy=E_TT_FUSION,
        num_neutrons=2,
        cross_section=TT_XS,
        bosch_hale_coefficients=None,
        ballabio_spectrum=None,
    )

D_D = <Reactions.D_D: ReactionData(label='D + D → ³He + n', total_energy=5.237367559215132e-13, num_neutrons=1, cross_section=<tokamak_neutron_source.reactivity_data.ReactionCrossSection object at 0x7ff2008dfb10>, bosch_hale_coefficients=BoschHaleCoefficients(name='D + D --> 3He + n', t_min=0.2, t_max=100.0, bg=31.397, mrc2=937814.0, c=array([ 5.43360e-12, 5.85778e-03, 7.68222e-03, 0.00000e+00,-2.96400e-06, 0.00000e+00, 0.00000e+00])), ballabio_spectrum=BallabioEnergySpectrum(energy_0=2449.5, omega_0=82.542, energy_shift_coeffs=BallabioCoefficients(a1=4.69515, a2=-0.040729, a3=0.47, a4=0.81844), width_correction_coeffs=BallabioCoefficients(a1=0.0017013, a2=0.16888, a3=0.49, a4=0.0007946)))> class-attribute

Neutronic reaction channels.

D_T = <Reactions.D_T: ReactionData(label='D + T → ⁴He + n', total_energy=2.8183035155819573e-12, num_neutrons=1, cross_section=<tokamak_neutron_source.reactivity_data.ReactionCrossSection object at 0x7ff2008d4c50>, bosch_hale_coefficients=BoschHaleCoefficients(name='D + T --> 4He + n', t_min=0.2, t_max=100.0, bg=34.3827, mrc2=1124656.0, c=array([ 1.17302e-09, 1.51361e-02, 7.51886e-02, 4.60643e-03,1.35000e-02, -1.06750e-04, 1.36600e-05])), ballabio_spectrum=BallabioEnergySpectrum(energy_0=14021.0, omega_0=177.259, energy_shift_coeffs=BallabioCoefficients(a1=5.30509, a2=0.0024736, a3=1.84, a4=1.3818), width_correction_coeffs=BallabioCoefficients(a1=0.00051068, a2=0.0076223, a3=1.78, a4=8.7691e-05)))> class-attribute

Neutronic reaction channels.

T_T = <Reactions.T_T: ReactionData(label='T + T → ⁴He + 2n', total_energy=1.8157845541890245e-12, num_neutrons=2, cross_section=<tokamak_neutron_source.reactivity_data.ReactionCrossSection object at 0x7ff20ad03850>, bosch_hale_coefficients=None, ballabio_spectrum=None)> class-attribute

Neutronic reaction channels.

AneutronicReactions

Bases: tokamak_neutron_source.reactions.ReactionEnumMixin, enum.Enum

Aneutronic reaction channels.

Source code in tokamak_neutron_source/reactions.py
class AneutronicReactions(ReactionEnumMixin, Enum):
    """Aneutronic reaction channels."""

    D_D = ReactionData(
        label="D + D → T + p",
        total_energy=E_DD_TP_FUSION,
        num_neutrons=0,  # no neutrons in aneutronic branch
        cross_section=DD_TP_XS,
        bosch_hale_coefficients=BOSCH_HALE_DD_TP,
        ballabio_spectrum=None,
    )
    D_He3 = ReactionData(
        label="D + ³He → ⁴He + p",
        total_energy=E_DHE3_FUSION,
        num_neutrons=0,
        cross_section=DHE3_HEP_XS,
        bosch_hale_coefficients=None,
        ballabio_spectrum=None,
    )

D_D = <AneutronicReactions.D_D: ReactionData(label='D + D → T + p', total_energy=6.461016407480568e-13, num_neutrons=0, cross_section=<tokamak_neutron_source.reactivity_data.ReactionCrossSection object at 0x7ff2008b80d0>, bosch_hale_coefficients=BoschHaleCoefficients(name='D + D --> T + p', t_min=0.2, t_max=100.0, bg=31.397, mrc2=937814.0, c=array([5.65718e-12, 3.41267e-03, 1.99167e-03, 0.00000e+00, 1.05060e-05,0.00000e+00, 0.00000e+00])), ballabio_spectrum=None)> class-attribute

Aneutronic reaction channels.

D_He3 = <AneutronicReactions.D_He3: ReactionData(label='D + ³He → ⁴He + p', total_energy=2.940668400408501e-12, num_neutrons=0, cross_section=<tokamak_neutron_source.reactivity_data.ReactionCrossSection object at 0x7ff200901310>, bosch_hale_coefficients=None, ballabio_spectrum=None)> class-attribute

Aneutronic reaction channels.

BallabioEnergySpectrum

Ballabio et al. fit data for relativistic fusion reaction neutron energy Gaussian spectra.

Source code in tokamak_neutron_source/energy_data.py
@dataclass
class BallabioEnergySpectrum:
    """
    Ballabio et al. fit data for relativistic fusion reaction neutron energy Gaussian
    spectra.
    """

    """E_0"""
    energy_0: float  # [keV]

    omega_0: float  # [keV]

    r"""\Delta E_{th} coefficients"""
    energy_shift_coeffs: BallabioCoefficients

    r"""\delta_{\omega} coefficients"""
    width_correction_coeffs: BallabioCoefficients

    def energy_shift(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
        r"""
        Calculate the energy shift \Delta E_{th} at a given ion temperature.
        """  # noqa: DOC201
        return self.energy_shift_coeffs.fit(temp_kev)

    def width_correction(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
        r"""
        Calculate the width correction \delta_{\omega} at a given ion temperature.
        """  # noqa: DOC201
        return self.width_correction_coeffs.fit(temp_kev)

    def mean_energy(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
        """
        Calculate the mean neutron energy at a given ion temperature
        (primary first moment: mu).
        """  # noqa: DOC201
        return self.energy_0 + self.energy_shift(temp_kev)

    def std_deviation(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
        """
        Calculate the standard deviation of the neutron energy spectrum at a given ion
        temperature (primary second moment: sigma)
        """  # noqa: DOC201
        # Full width at half maximum (FWHM)
        w_12 = self.omega_0 * (1 + self.width_correction(temp_kev)) * np.sqrt(temp_kev)
        return w_12 / TWO_SQRT_2LN2

energy_shift(temp_kev)

Calculate the energy shift \Delta E_{th} at a given ion temperature.

Source code in tokamak_neutron_source/energy_data.py
def energy_shift(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
    r"""
    Calculate the energy shift \Delta E_{th} at a given ion temperature.
    """  # noqa: DOC201
    return self.energy_shift_coeffs.fit(temp_kev)

mean_energy(temp_kev)

Calculate the mean neutron energy at a given ion temperature (primary first moment: mu).

Source code in tokamak_neutron_source/energy_data.py
def mean_energy(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
    """
    Calculate the mean neutron energy at a given ion temperature
    (primary first moment: mu).
    """  # noqa: DOC201
    return self.energy_0 + self.energy_shift(temp_kev)

std_deviation(temp_kev)

Calculate the standard deviation of the neutron energy spectrum at a given ion temperature (primary second moment: sigma)

Source code in tokamak_neutron_source/energy_data.py
def std_deviation(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
    """
    Calculate the standard deviation of the neutron energy spectrum at a given ion
    temperature (primary second moment: sigma)
    """  # noqa: DOC201
    # Full width at half maximum (FWHM)
    w_12 = self.omega_0 * (1 + self.width_correction(temp_kev)) * np.sqrt(temp_kev)
    return w_12 / TWO_SQRT_2LN2

width_correction(temp_kev)

Calculate the width correction \delta_{\omega} at a given ion temperature.

Source code in tokamak_neutron_source/energy_data.py
def width_correction(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
    r"""
    Calculate the width correction \delta_{\omega} at a given ion temperature.
    """  # noqa: DOC201
    return self.width_correction_coeffs.fit(temp_kev)

BoschHaleCoefficients

Bosch-Hale parameterisation dataclass.

H.-S. Bosch and G.M. Hale 1992 Nucl. Fusion 32 611 DOI 10.1088/0029-5515/32/4/I07

Source code in tokamak_neutron_source/reactivity_data.py
@dataclass
class BoschHaleCoefficients:
    """
    Bosch-Hale parameterisation dataclass.

    H.-S. Bosch and G.M. Hale 1992 Nucl. Fusion 32 611
    DOI 10.1088/0029-5515/32/4/I07
    """

    name: str
    t_min: float  # [keV]
    t_max: float  # [keV]
    bg: float  # [keV**0.5]
    mrc2: float  # [keV]
    c: npt.NDArray

ReactionCrossSection

Fusion reaction cross-section.

Source code in tokamak_neutron_source/reactivity_data.py
class ReactionCrossSection:
    """Fusion reaction cross-section."""

    def __init__(self, file_name: str):
        """
        Parameters
        ----------
        file_name:
            Cross-sectional data file (ENDF format)

        Raises
        ------
        ReactivityError
            Data file path is not a file
        """
        path = get_tns_path("data/cross_sections")
        path = Path(path, file_name)
        if not path.is_file():
            raise ReactivityError(f"Cross-section data file {path} is not a file!")

        file = path.as_posix()
        # Read in the cross section (in barn) as a function of energy (MeV).
        energy, sigma = np.genfromtxt(file, comments="#", skip_footer=2, unpack=True)

        split = file_name.split(".", maxsplit=1)[0].split("_")
        collider, target = split[:2]
        self.name = f"{collider} + {target} -> {split[2]} + {split[3]}"

        mass_1, mass_2 = MOLAR_MASSES[collider], MOLAR_MASSES[target]

        self.reduced_mass = raw_uc(mass_1 * mass_2 / (mass_1 + mass_2), "amu", "kg")

        # Convert to center of mass frame
        # NOTE MC: Choice of target/collider thing makes Bosch-Hale line up...
        energy *= mass_2 / (mass_1 + mass_2)

        # Convert to kev / m^2
        self._cross_section = interp1d(energy * 1e3, sigma * 1e-28)

    def __call__(self, temp_kev: float | npt.NDArray) -> float | npt.NDArray:
        """Get cross section at a give temperature"""  # noqa: DOC201
        return self._cross_section(temp_kev)

ReactivityError

Bases: tokamak_neutron_source.error.TNSError

Reactivity error class

Source code in tokamak_neutron_source/error.py
class ReactivityError(TNSError):
    """Reactivity error class"""

DD_HE3N_XS(temp_kev)

Fusion reaction cross-section.

DD_TP_XS(temp_kev)

Fusion reaction cross-section.

DHE3_HEP_XS(temp_kev)

Fusion reaction cross-section.

DT_XS(temp_kev)

Fusion reaction cross-section.

TT_XS(temp_kev)

Fusion reaction cross-section.