Path: blob/main/latex-templates/templates/nuclear-physics/radioactive_decay.tex
51 views
unlisted
\documentclass[a4paper, 11pt]{article}1\usepackage[utf8]{inputenc}2\usepackage[T1]{fontenc}3\usepackage{amsmath, amssymb, amsthm}4\usepackage{graphicx}5\usepackage{booktabs}6\usepackage{siunitx}7\usepackage{subcaption}8\usepackage[makestderr]{pythontex}910\newtheorem{definition}{Definition}11\newtheorem{theorem}{Theorem}12\newtheorem{example}{Example}13\newtheorem{remark}{Remark}1415\title{Radioactive Decay Chains: Bateman Equations and Activity Calculations}16\author{Nuclear Physics Computation Laboratory}17\date{\today}1819\begin{document}20\maketitle2122\begin{abstract}23This technical report presents comprehensive computational analysis of radioactive decay chains using the Bateman equations. We implement solutions for sequential decay series, compute activities as functions of time, and analyze equilibrium conditions including secular and transient equilibrium. Applications include medical isotope production, nuclear waste management, radiometric dating, and radiation dosimetry.24\end{abstract}2526\section{Theoretical Framework}2728\begin{definition}[Radioactive Decay Law]29The decay of radioactive nuclei follows first-order kinetics:30\begin{equation}31\frac{dN}{dt} = -\lambda N32\end{equation}33where $\lambda = \ln(2)/t_{1/2}$ is the decay constant and $t_{1/2}$ is the half-life.34\end{definition}3536\begin{theorem}[Bateman Equations]37For a decay chain $N_1 \to N_2 \to N_3 \to \cdots$, the populations evolve as:38\begin{align}39\frac{dN_1}{dt} &= -\lambda_1 N_1 \\40\frac{dN_2}{dt} &= \lambda_1 N_1 - \lambda_2 N_2 \\41\frac{dN_n}{dt} &= \lambda_{n-1} N_{n-1} - \lambda_n N_n42\end{align}43with solution:44\begin{equation}45N_n(t) = N_1(0) \prod_{i=1}^{n-1} \lambda_i \sum_{i=1}^{n} \frac{e^{-\lambda_i t}}{\prod_{j \neq i}(\lambda_j - \lambda_i)}46\end{equation}47\end{theorem}4849\subsection{Activity and Equilibrium}5051\begin{definition}[Activity]52The activity $A = \lambda N$ is the number of decays per unit time, measured in Becquerels (Bq = decays/s) or Curies (1 Ci = $3.7 \times 10^{10}$ Bq).53\end{definition}5455\begin{example}[Equilibrium Conditions]56For a two-member chain with $\lambda_1 \ll \lambda_2$:57\begin{itemize}58\item \textbf{Secular equilibrium}: $A_2 \approx A_1$ (daughter activity equals parent)59\item \textbf{Transient equilibrium}: $A_2/A_1 = \lambda_2/(\lambda_2 - \lambda_1)$60\end{itemize}61\end{example}6263\section{Computational Analysis}6465\begin{pycode}66import numpy as np67from scipy.integrate import odeint, solve_ivp68import matplotlib.pyplot as plt69plt.rc('text', usetex=True)70plt.rc('font', family='serif', size=10)7172# Time unit conversions73sec_per_hour = 360074sec_per_day = 8640075sec_per_year = 365.25 * sec_per_day7677# Decay chain class78class DecayChain:79def __init__(self, half_lives, names):80self.names = names81self.half_lives = np.array(half_lives)82self.lambdas = np.log(2) / self.half_lives83self.n = len(half_lives)8485def equations(self, N, t):86dNdt = np.zeros(self.n)87dNdt[0] = -self.lambdas[0] * N[0]88for i in range(1, self.n):89if self.lambdas[i] > 0: # Not stable90dNdt[i] = self.lambdas[i-1] * N[i-1] - self.lambdas[i] * N[i]91else:92dNdt[i] = self.lambdas[i-1] * N[i-1]93return dNdt9495def solve(self, N0, t):96return odeint(self.equations, N0, t)9798def activity(self, N):99return N * self.lambdas100101# Mo-99/Tc-99m generator (medical isotopes)102mo_tc_chain = DecayChain(103half_lives=[66.0 * sec_per_hour, 6.0 * sec_per_hour, 1e20],104names=['Mo-99', 'Tc-99m', 'Tc-99']105)106107# Initial conditions (pure Mo-99)108N0_mo = [1.0, 0.0, 0.0]109t_mo = np.linspace(0, 200 * sec_per_hour, 1000)110sol_mo = mo_tc_chain.solve(N0_mo, t_mo)111A_mo = mo_tc_chain.activity(sol_mo)112113# Find optimal milking time114tc99m_activity = A_mo[:, 1]115max_idx = np.argmax(tc99m_activity)116t_max_tc = t_mo[max_idx] / sec_per_hour117A_max_tc = tc99m_activity[max_idx]118119# Equilibrium ratio120lambda_1, lambda_2 = mo_tc_chain.lambdas[0], mo_tc_chain.lambdas[1]121equilibrium_ratio = lambda_2 / (lambda_2 - lambda_1)122123# Uranium-238 decay series (simplified)124# U-238 -> Th-234 -> Pa-234 -> U-234 -> ...125u238_chain = DecayChain(126half_lives=[4.47e9 * sec_per_year, 24.1 * sec_per_day,1271.17 / 60 * sec_per_hour, 2.45e5 * sec_per_year],128names=['U-238', 'Th-234', 'Pa-234', 'U-234']129)130131N0_u = [1.0, 0.0, 0.0, 0.0]132t_u = np.linspace(0, 365 * sec_per_day, 1000) # 1 year133sol_u = u238_chain.solve(N0_u, t_u)134A_u = u238_chain.activity(sol_u)135136# Branching decay example: Bi-212137# Bi-212 -> Po-212 (64%) or Tl-208 (36%)138bi212_hl = 60.6 * 60 # seconds139po212_hl = 0.3e-6 # microseconds140tl208_hl = 3.05 * 60 # seconds141142branch_alpha = 0.64143branch_beta = 0.36144145# Radon-222 and daughters for dosimetry146rn_chain = DecayChain(147half_lives=[3.8 * sec_per_day, 3.05 * 60, 26.8 * 60,1481e-4, 22.3 * sec_per_year],149names=['Rn-222', 'Po-218', 'Pb-214', 'Bi-214', 'Pb-210']150)151152# Carbon-14 dating153c14_half_life = 5730 * sec_per_year154lambda_c14 = np.log(2) / c14_half_life155156def carbon_dating_age(ratio):157"""Calculate age from C-14/C-12 ratio relative to modern."""158return -np.log(ratio) / lambda_c14 / sec_per_year159160# Medical isotopes table161medical_isotopes = [162('Mo-99/Tc-99m', 66.0, 6.0, 'Imaging'),163('I-131', 8.02 * 24, np.inf, 'Thyroid'),164('F-18', 1.83, np.inf, 'PET'),165('Co-60', 5.27 * 365 * 24, np.inf, 'Therapy'),166('Cs-137', 30.17 * 365 * 24, np.inf, 'Calibration')167]168169# Multi-stage decay with numerical solution170def bateman_analytical_2stage(t, lambda1, lambda2, N10):171"""Analytical Bateman solution for 2-stage decay."""172N1 = N10 * np.exp(-lambda1 * t)173if abs(lambda2 - lambda1) > 1e-10:174N2 = N10 * lambda1 / (lambda2 - lambda1) * (np.exp(-lambda1 * t) - np.exp(-lambda2 * t))175else:176N2 = N10 * lambda1 * t * np.exp(-lambda1 * t)177return N1, N2178179# Create visualization180fig = plt.figure(figsize=(12, 10))181gs = fig.add_gridspec(3, 3, hspace=0.35, wspace=0.35)182183# Plot 1: Mo-99/Tc-99m populations184ax1 = fig.add_subplot(gs[0, 0])185ax1.plot(t_mo / sec_per_hour, sol_mo[:, 0], 'b-', lw=2, label='Mo-99')186ax1.plot(t_mo / sec_per_hour, sol_mo[:, 1], 'r-', lw=2, label='Tc-99m')187ax1.plot(t_mo / sec_per_hour, sol_mo[:, 2], 'g--', lw=1.5, label='Tc-99')188ax1.set_xlabel('Time (hours)')189ax1.set_ylabel('Relative Population')190ax1.set_title('Mo-99/Tc-99m Generator')191ax1.legend(fontsize=7)192ax1.grid(True, alpha=0.3)193194# Plot 2: Activities195ax2 = fig.add_subplot(gs[0, 1])196ax2.plot(t_mo / sec_per_hour, A_mo[:, 0] / A_mo[0, 0], 'b-', lw=2, label='$A_1$ (Mo-99)')197ax2.plot(t_mo / sec_per_hour, A_mo[:, 1] / A_mo[0, 0], 'r-', lw=2, label='$A_2$ (Tc-99m)')198ax2.axvline(x=t_max_tc, color='gray', ls='--', alpha=0.5)199ax2.set_xlabel('Time (hours)')200ax2.set_ylabel('Relative Activity')201ax2.set_title('Decay Activities')202ax2.legend(fontsize=7)203ax2.grid(True, alpha=0.3)204205# Plot 3: Activity ratio (transient equilibrium)206ax3 = fig.add_subplot(gs[0, 2])207ratio = A_mo[:, 1] / (A_mo[:, 0] + 1e-20)208ax3.plot(t_mo / sec_per_hour, ratio, 'purple', lw=2)209ax3.axhline(y=equilibrium_ratio, color='r', ls='--',210label=f'Equilibrium: {equilibrium_ratio:.3f}')211ax3.set_xlabel('Time (hours)')212ax3.set_ylabel('$A_2/A_1$')213ax3.set_title('Activity Ratio')214ax3.legend(fontsize=7)215ax3.grid(True, alpha=0.3)216ax3.set_ylim([0, equilibrium_ratio * 1.2])217218# Plot 4: U-238 daughters approach secular equilibrium219ax4 = fig.add_subplot(gs[1, 0])220for i in range(1, 4):221ax4.plot(t_u / sec_per_day, A_u[:, i] / (A_u[0, 0] + 1e-20),222lw=1.5, label=u238_chain.names[i])223ax4.set_xlabel('Time (days)')224ax4.set_ylabel('Activity / Initial $A_0$')225ax4.set_title('U-238 Daughters (Secular Equil.)')226ax4.legend(fontsize=7)227ax4.grid(True, alpha=0.3)228ax4.set_yscale('log')229230# Plot 5: Decay curve fitting231ax5 = fig.add_subplot(gs[1, 1])232t_decay = np.linspace(0, 5, 100) # In half-lives233y_decay = np.exp(-np.log(2) * t_decay)234235# Add noise for fitting demonstration236np.random.seed(42)237t_data = np.array([0, 0.5, 1, 1.5, 2, 3, 4])238y_data = np.exp(-np.log(2) * t_data) + np.random.normal(0, 0.02, len(t_data))239240ax5.plot(t_decay, y_decay, 'b-', lw=2, label='Theory')241ax5.scatter(t_data, y_data, color='red', s=50, zorder=5, label='Data')242ax5.axhline(y=0.5, color='gray', ls='--', alpha=0.5)243ax5.axvline(x=1, color='gray', ls='--', alpha=0.5)244ax5.set_xlabel('Time / $t_{1/2}$')245ax5.set_ylabel('$N/N_0$')246ax5.set_title('Radioactive Decay Curve')247ax5.legend(fontsize=8)248ax5.grid(True, alpha=0.3)249250# Plot 6: Carbon-14 dating251ax6 = fig.add_subplot(gs[1, 2])252ratios = np.linspace(0.01, 1.0, 100)253ages = np.array([carbon_dating_age(r) for r in ratios])254255ax6.plot(ages / 1000, ratios, 'g-', lw=2)256ax6.axhline(y=0.5, color='gray', ls='--', alpha=0.5)257ax6.axvline(x=5.73, color='gray', ls='--', alpha=0.5)258ax6.set_xlabel('Age (kyr)')259ax6.set_ylabel('$^{14}$C / $^{14}$C$_0$')260ax6.set_title('Carbon-14 Dating')261ax6.grid(True, alpha=0.3)262ax6.set_xlim([0, 50])263264# Plot 7: Half-lives comparison265ax7 = fig.add_subplot(gs[2, 0])266isotope_names = [m[0].split('/')[0] if '/' in m[0] else m[0] for m in medical_isotopes]267half_lives_hr = [m[1] for m in medical_isotopes]268colors = ['blue', 'red', 'green', 'orange', 'purple']269270ax7.barh(isotope_names, np.log10(half_lives_hr), color=colors, alpha=0.7)271ax7.set_xlabel('$\\log_{10}(t_{1/2} / \\mathrm{hours})$')272ax7.set_title('Medical Isotope Half-Lives')273ax7.grid(True, alpha=0.3, axis='x')274275# Plot 8: Generator elution cycles276ax8 = fig.add_subplot(gs[2, 1])277t_cycle = np.linspace(0, 100, 1000)278elution_times = [0, 24, 48, 72]279280# Simulate multiple elutions281N_mo = np.ones_like(t_cycle)282N_tc = np.zeros_like(t_cycle)283284for i, t in enumerate(t_cycle):285# Decay between elutions286hours = t287N_mo[i] = np.exp(-lambda_1 * hours * sec_per_hour)288289# Tc-99m builds up290N_tc[i] = (lambda_1 / (lambda_2 - lambda_1)) * N_mo[i] * \291(1 - np.exp(-(lambda_2 - lambda_1) * (hours % 24) * sec_per_hour))292293ax8.plot(t_cycle, N_tc * lambda_2 / lambda_1, 'r-', lw=2)294for et in elution_times[1:]:295ax8.axvline(x=et, color='blue', ls='--', alpha=0.5)296ax8.set_xlabel('Time (hours)')297ax8.set_ylabel('Tc-99m Activity')298ax8.set_title('Generator Elution Cycles')299ax8.grid(True, alpha=0.3)300301# Plot 9: Specific activity302ax9 = fig.add_subplot(gs[2, 2])303A_range = np.logspace(0, 3, 100) # Mass numbers304305# Specific activity = lambda * N_A / A306N_A = 6.022e23 # Avogadro's number307t_half_1yr = sec_per_year308309specific_act = np.log(2) / t_half_1yr * N_A / A_range / 1e12 # TBq/g310311ax9.loglog(A_range, specific_act, 'b-', lw=2)312ax9.set_xlabel('Mass Number $A$')313ax9.set_ylabel('Specific Activity (TBq/g)')314ax9.set_title('Specific Activity ($t_{1/2}$ = 1 yr)')315ax9.grid(True, alpha=0.3, which='both')316317plt.savefig('radioactive_decay_plot.pdf', bbox_inches='tight', dpi=150)318print(r'\begin{center}')319print(r'\includegraphics[width=\textwidth]{radioactive_decay_plot.pdf}')320print(r'\end{center}')321plt.close()322323# Summary calculations324N_A_value = 6.022e23325specific_mo99 = np.log(2) / (66 * sec_per_hour) * N_A_value / 99 / 1e12326\end{pycode}327328\section{Results and Analysis}329330\subsection{Mo-99/Tc-99m Generator}331332\begin{pycode}333print(r'\begin{table}[htbp]')334print(r'\centering')335print(r'\caption{Mo-99/Tc-99m Generator Characteristics}')336print(r'\begin{tabular}{lcc}')337print(r'\toprule')338print(r'Parameter & Value & Units \\')339print(r'\midrule')340print(f'Mo-99 half-life & {66.0:.1f} & hours \\\\')341print(f'Tc-99m half-life & {6.0:.1f} & hours \\\\')342print(f'Optimal elution time & {t_max_tc:.1f} & hours \\\\')343print(f'Equilibrium ratio $A_2/A_1$ & {equilibrium_ratio:.3f} & -- \\\\')344print(f'Time to 90\\% equilibrium & {-np.log(0.1)/lambda_2/sec_per_hour:.1f} & hours \\\\')345print(r'\bottomrule')346print(r'\end{tabular}')347print(r'\end{table}')348\end{pycode}349350\begin{remark}351The Mo-99/Tc-99m generator reaches transient equilibrium because $\lambda_2 > \lambda_1$. The daughter activity exceeds the parent activity by the factor $\lambda_2/(\lambda_2 - \lambda_1) = \py{f"{equilibrium_ratio:.2f}"}$.352\end{remark}353354\subsection{Medical Isotopes}355356\begin{pycode}357print(r'\begin{table}[htbp]')358print(r'\centering')359print(r'\caption{Medical Radioisotopes}')360print(r'\begin{tabular}{lccl}')361print(r'\toprule')362print(r'Isotope & $t_{1/2}$ & Production & Application \\')363print(r'\midrule')364print(r'Tc-99m & 6.0 hr & Generator & SPECT imaging \\')365print(r'F-18 & 110 min & Cyclotron & PET imaging \\')366print(r'I-131 & 8.0 days & Reactor & Thyroid therapy \\')367print(r'Co-60 & 5.3 yr & Reactor & External beam therapy \\')368print(r'Ir-192 & 74 days & Reactor & Brachytherapy \\')369print(r'\bottomrule')370print(r'\end{tabular}')371print(r'\end{table}')372\end{pycode}373374\subsection{Equilibrium Types}375376\begin{theorem}[Secular Equilibrium]377When $\lambda_1 \ll \lambda_2$ (parent half-life much longer than daughter):378\begin{equation}379A_2 \approx A_1 \quad \text{for } t \gg t_{1/2,2}380\end{equation}381Example: U-238 series where U-238 ($t_{1/2} = 4.5 \times 10^9$ yr) decays to short-lived daughters.382\end{theorem}383384\begin{theorem}[Transient Equilibrium]385When $\lambda_1 < \lambda_2$ but comparable:386\begin{equation}387\frac{A_2}{A_1} = \frac{\lambda_2}{\lambda_2 - \lambda_1}388\end{equation}389Example: Mo-99/Tc-99m where ratio $= \py{f"{equilibrium_ratio:.2f}"}$.390\end{theorem}391392\section{Applications}393394\begin{example}[Radiometric Dating]395Carbon-14 dating uses the decay:396\begin{equation}397^{14}\text{C} \to ^{14}\text{N} + \beta^- + \bar{\nu}_e398\end{equation}399with $t_{1/2} = 5730$ years. Measurable ages range from $\sim$300 to 50,000 years.400\end{example}401402\begin{example}[Nuclear Waste Management]403The activity of fission products decreases as:404\begin{itemize}405\item Short-term (1-100 yr): dominated by Cs-137, Sr-90406\item Intermediate (100-1000 yr): Sm-151, Tc-99407\item Long-term ($>$1000 yr): actinides (Pu, Am, Cm)408\end{itemize}409\end{example}410411\section{Discussion}412413The Bateman equations provide a complete description of radioactive decay chains:414415\begin{enumerate}416\item \textbf{Generator design}: Optimal elution times maximize daughter activity while balancing parent depletion.417\item \textbf{Diagnostic imaging}: Short-lived isotopes minimize patient dose while providing adequate counts.418\item \textbf{Dose calculations}: Activity profiles determine internal dosimetry for therapy planning.419\item \textbf{Environmental monitoring}: Equilibrium assumptions simplify radon progeny measurements.420\end{enumerate}421422\section{Conclusions}423424This computational analysis demonstrates:425\begin{itemize}426\item Tc-99m maximum activity at $t = \py{f"{t_max_tc:.1f}"}$ hours427\item Transient equilibrium ratio: \py{f"{equilibrium_ratio:.3f}"}428\item Specific activity of Mo-99: \py{f"{specific_mo99:.0f}"} TBq/g429\item C-14 dating range: 300 -- 50,000 years430\end{itemize}431432The Bateman equations enable precise prediction of radionuclide behavior for medical, industrial, and research applications.433434\section{Further Reading}435\begin{itemize}436\item Magill, J., Galy, J., \textit{Radioactivity Radionuclides Radiation}, Springer, 2005437\item Loveland, W.D., Morrissey, D.J., Seaborg, G.T., \textit{Modern Nuclear Chemistry}, 2nd Ed., Wiley, 2017438\item Cherry, S.R., Sorenson, J.A., Phelps, M.E., \textit{Physics in Nuclear Medicine}, 4th Ed., Elsevier, 2012439\end{itemize}440441\end{document}442443444