Path: blob/main/latex-templates/templates/astrophysics/galaxy_dynamics.tex
51 views
unlisted
% Galaxy Dynamics1\documentclass[11pt,a4paper]{article}2\usepackage[utf8]{inputenc}3\usepackage[T1]{fontenc}4\usepackage{amsmath,amssymb}5\usepackage{graphicx}6\usepackage{booktabs}7\usepackage{siunitx}8\usepackage{geometry}9\geometry{margin=1in}10\usepackage{pythontex}11\usepackage{hyperref}12\usepackage{float}1314\title{Galaxy Dynamics\\Rotation Curves and Dark Matter}15\author{Extragalactic Astronomy Group}16\date{\today}1718\begin{document}19\maketitle2021\begin{abstract}22Analysis of galaxy dynamics including rotation curves, dark matter profiles, and scaling relations.23\end{abstract}2425\section{Introduction}2627Galaxy rotation curves provide evidence for dark matter.2829\begin{pycode}30import numpy as np31import matplotlib.pyplot as plt32plt.rcParams['text.usetex'] = True33plt.rcParams['font.family'] = 'serif'3435G = 4.302e-6 # kpc (km/s)^2 / M_sun36\end{pycode}3738\section{Rotation Curve Components}3940\begin{pycode}41r = np.linspace(0.1, 30, 200) # kpc4243# Bulge (Hernquist profile)44M_b = 1e1045a_b = 0.546v_bulge = np.sqrt(G * M_b * r / (r + a_b)**2)4748# Disk (exponential)49M_d = 5e1050R_d = 3.551y = r / (2 * R_d)52v_disk = np.sqrt(G * M_d * r**2 / R_d**3 * (0.5 - y + y**2 * np.exp(-2*y)))5354# Dark matter halo (NFW)55M_h = 1e1256c = 1057r_s = 2058x = r / r_s59v_halo = np.sqrt(G * M_h * (np.log(1 + x) - x/(1 + x)) / (r * (np.log(1 + c) - c/(1 + c))))6061# Total62v_total = np.sqrt(v_bulge**2 + v_disk**2 + v_halo**2)6364fig, ax = plt.subplots(figsize=(10, 6))65ax.plot(r, v_bulge, '--', label='Bulge', linewidth=1.5)66ax.plot(r, v_disk, '--', label='Disk', linewidth=1.5)67ax.plot(r, v_halo, '--', label='Dark Matter Halo', linewidth=1.5)68ax.plot(r, v_total, 'k-', label='Total', linewidth=2)69ax.set_xlabel('Radius (kpc)')70ax.set_ylabel('Rotation Velocity (km/s)')71ax.set_title('Galaxy Rotation Curve Decomposition')72ax.legend()73ax.grid(True, alpha=0.3)74ax.set_xlim([0, 30])75ax.set_ylim([0, 300])76plt.tight_layout()77plt.savefig('rotation_curve.pdf', dpi=150, bbox_inches='tight')78plt.close()79\end{pycode}8081\begin{figure}[H]82\centering83\includegraphics[width=0.9\textwidth]{rotation_curve.pdf}84\caption{Rotation curve decomposition showing different components.}85\end{figure}8687\section{NFW Profile}8889$\rho(r) = \frac{\rho_s}{(r/r_s)(1+r/r_s)^2}$9091\begin{pycode}92r_nfw = np.logspace(-1, 2, 100)93rho_s = 1e7 # M_sun / kpc^39495for c in [5, 10, 20]:96r_s = 20 / c * 1097x = r_nfw / r_s98rho = rho_s / (x * (1 + x)**2)99plt.loglog(r_nfw, rho, label=f'c = {c}')100101plt.xlabel('Radius (kpc)')102plt.ylabel('Density ($M_\\odot$/kpc$^3$)')103plt.title('NFW Dark Matter Density Profile')104plt.legend()105plt.grid(True, alpha=0.3, which='both')106plt.tight_layout()107plt.savefig('nfw_profile.pdf', dpi=150, bbox_inches='tight')108plt.close()109\end{pycode}110111\begin{figure}[H]112\centering113\includegraphics[width=0.9\textwidth]{nfw_profile.pdf}114\caption{NFW density profiles for different concentrations.}115\end{figure}116117\section{Tully-Fisher Relation}118119$M_B = a \log_{10} V_{max} + b$120121\begin{pycode}122# Generate mock data123np.random.seed(42)124V_max = np.random.uniform(100, 300, 50)125M_B = -7.5 * np.log10(V_max) + 3.5 + np.random.normal(0, 0.3, 50)126127fig, ax = plt.subplots(figsize=(10, 6))128ax.scatter(np.log10(V_max), M_B, alpha=0.7)129# Fit line130coeffs = np.polyfit(np.log10(V_max), M_B, 1)131V_fit = np.linspace(100, 300, 100)132ax.plot(np.log10(V_fit), np.polyval(coeffs, np.log10(V_fit)), 'r-', linewidth=2)133ax.set_xlabel('log$_{10}$ $V_{max}$ (km/s)')134ax.set_ylabel('$M_B$ (mag)')135ax.set_title('Tully-Fisher Relation')136ax.invert_yaxis()137ax.grid(True, alpha=0.3)138plt.tight_layout()139plt.savefig('tully_fisher.pdf', dpi=150, bbox_inches='tight')140plt.close()141\end{pycode}142143\begin{figure}[H]144\centering145\includegraphics[width=0.9\textwidth]{tully_fisher.pdf}146\caption{Tully-Fisher relation for spiral galaxies.}147\end{figure}148149\section{Dark Matter Fraction}150151\begin{pycode}152r_frac = np.linspace(0.1, 30, 100)153M_baryon = M_b * r_frac**2 / (r_frac + a_b)**2 + M_d * (1 - (1 + r_frac/R_d) * np.exp(-r_frac/R_d))154x_frac = r_frac / r_s155M_dm = M_h * (np.log(1 + x_frac) - x_frac/(1 + x_frac)) / (np.log(1 + c) - c/(1 + c))156f_dm = M_dm / (M_dm + M_baryon)157158fig, ax = plt.subplots(figsize=(10, 6))159ax.plot(r_frac, f_dm, 'b-', linewidth=2)160ax.axhline(y=0.5, color='r', linestyle='--')161ax.set_xlabel('Radius (kpc)')162ax.set_ylabel('Dark Matter Fraction')163ax.set_title('Enclosed Dark Matter Fraction')164ax.grid(True, alpha=0.3)165ax.set_xlim([0, 30])166ax.set_ylim([0, 1])167plt.tight_layout()168plt.savefig('dm_fraction.pdf', dpi=150, bbox_inches='tight')169plt.close()170\end{pycode}171172\begin{figure}[H]173\centering174\includegraphics[width=0.9\textwidth]{dm_fraction.pdf}175\caption{Dark matter fraction vs radius.}176\end{figure}177178\section{Velocity Dispersion}179180\begin{pycode}181# Stellar velocity dispersion profile182r_sigma = np.linspace(0.1, 10, 100)183sigma_0 = 200 # km/s184r_e = 2 # Effective radius185sigma = sigma_0 * (1 + r_sigma / r_e)**(-0.5)186187fig, ax = plt.subplots(figsize=(10, 6))188ax.plot(r_sigma, sigma, 'b-', linewidth=2)189ax.set_xlabel('Radius (kpc)')190ax.set_ylabel('Velocity Dispersion (km/s)')191ax.set_title('Stellar Velocity Dispersion Profile')192ax.grid(True, alpha=0.3)193plt.tight_layout()194plt.savefig('velocity_dispersion.pdf', dpi=150, bbox_inches='tight')195plt.close()196\end{pycode}197198\begin{figure}[H]199\centering200\includegraphics[width=0.9\textwidth]{velocity_dispersion.pdf}201\caption{Velocity dispersion profile.}202\end{figure}203204\section{Mass Modeling}205206\begin{pycode}207# Enclosed mass208M_enc = (v_total * r)**2 / (G * r) * r209210fig, ax = plt.subplots(figsize=(10, 6))211ax.semilogy(r, M_enc, 'b-', linewidth=2)212ax.set_xlabel('Radius (kpc)')213ax.set_ylabel('Enclosed Mass ($M_\\odot$)')214ax.set_title('Enclosed Mass Profile')215ax.grid(True, alpha=0.3, which='both')216plt.tight_layout()217plt.savefig('enclosed_mass.pdf', dpi=150, bbox_inches='tight')218plt.close()219\end{pycode}220221\begin{figure}[H]222\centering223\includegraphics[width=0.9\textwidth]{enclosed_mass.pdf}224\caption{Enclosed mass profile.}225\end{figure}226227\section{Results}228229\begin{pycode}230v_max = np.max(v_total)231r_max = r[np.argmax(v_total)]232print(r'\begin{table}[H]')233print(r'\centering')234print(r'\caption{Galaxy Model Parameters}')235print(r'\begin{tabular}{@{}lc@{}}')236print(r'\toprule')237print(r'Property & Value \\')238print(r'\midrule')239print(f'Maximum velocity & {v_max:.0f} km/s \\\\')240print(f'Radius at $V_{{max}}$ & {r_max:.1f} kpc \\\\')241print(f'Bulge mass & {M_b:.1e} $M_\\odot$ \\\\')242print(f'Disk mass & {M_d:.1e} $M_\\odot$ \\\\')243print(f'Halo mass & {M_h:.1e} $M_\\odot$ \\\\')244print(r'\bottomrule')245print(r'\end{tabular}')246print(r'\end{table}')247\end{pycode}248249\section{Conclusions}250251Galaxy rotation curves require dark matter halos to explain observations.252253\end{document}254255256