Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/astrophysics/galaxy_dynamics.tex
51 views
unlisted
1
% Galaxy Dynamics
2
\documentclass[11pt,a4paper]{article}
3
\usepackage[utf8]{inputenc}
4
\usepackage[T1]{fontenc}
5
\usepackage{amsmath,amssymb}
6
\usepackage{graphicx}
7
\usepackage{booktabs}
8
\usepackage{siunitx}
9
\usepackage{geometry}
10
\geometry{margin=1in}
11
\usepackage{pythontex}
12
\usepackage{hyperref}
13
\usepackage{float}
14
15
\title{Galaxy Dynamics\\Rotation Curves and Dark Matter}
16
\author{Extragalactic Astronomy Group}
17
\date{\today}
18
19
\begin{document}
20
\maketitle
21
22
\begin{abstract}
23
Analysis of galaxy dynamics including rotation curves, dark matter profiles, and scaling relations.
24
\end{abstract}
25
26
\section{Introduction}
27
28
Galaxy rotation curves provide evidence for dark matter.
29
30
\begin{pycode}
31
import numpy as np
32
import matplotlib.pyplot as plt
33
plt.rcParams['text.usetex'] = True
34
plt.rcParams['font.family'] = 'serif'
35
36
G = 4.302e-6 # kpc (km/s)^2 / M_sun
37
\end{pycode}
38
39
\section{Rotation Curve Components}
40
41
\begin{pycode}
42
r = np.linspace(0.1, 30, 200) # kpc
43
44
# Bulge (Hernquist profile)
45
M_b = 1e10
46
a_b = 0.5
47
v_bulge = np.sqrt(G * M_b * r / (r + a_b)**2)
48
49
# Disk (exponential)
50
M_d = 5e10
51
R_d = 3.5
52
y = r / (2 * R_d)
53
v_disk = np.sqrt(G * M_d * r**2 / R_d**3 * (0.5 - y + y**2 * np.exp(-2*y)))
54
55
# Dark matter halo (NFW)
56
M_h = 1e12
57
c = 10
58
r_s = 20
59
x = r / r_s
60
v_halo = np.sqrt(G * M_h * (np.log(1 + x) - x/(1 + x)) / (r * (np.log(1 + c) - c/(1 + c))))
61
62
# Total
63
v_total = np.sqrt(v_bulge**2 + v_disk**2 + v_halo**2)
64
65
fig, ax = plt.subplots(figsize=(10, 6))
66
ax.plot(r, v_bulge, '--', label='Bulge', linewidth=1.5)
67
ax.plot(r, v_disk, '--', label='Disk', linewidth=1.5)
68
ax.plot(r, v_halo, '--', label='Dark Matter Halo', linewidth=1.5)
69
ax.plot(r, v_total, 'k-', label='Total', linewidth=2)
70
ax.set_xlabel('Radius (kpc)')
71
ax.set_ylabel('Rotation Velocity (km/s)')
72
ax.set_title('Galaxy Rotation Curve Decomposition')
73
ax.legend()
74
ax.grid(True, alpha=0.3)
75
ax.set_xlim([0, 30])
76
ax.set_ylim([0, 300])
77
plt.tight_layout()
78
plt.savefig('rotation_curve.pdf', dpi=150, bbox_inches='tight')
79
plt.close()
80
\end{pycode}
81
82
\begin{figure}[H]
83
\centering
84
\includegraphics[width=0.9\textwidth]{rotation_curve.pdf}
85
\caption{Rotation curve decomposition showing different components.}
86
\end{figure}
87
88
\section{NFW Profile}
89
90
$\rho(r) = \frac{\rho_s}{(r/r_s)(1+r/r_s)^2}$
91
92
\begin{pycode}
93
r_nfw = np.logspace(-1, 2, 100)
94
rho_s = 1e7 # M_sun / kpc^3
95
96
for c in [5, 10, 20]:
97
r_s = 20 / c * 10
98
x = r_nfw / r_s
99
rho = rho_s / (x * (1 + x)**2)
100
plt.loglog(r_nfw, rho, label=f'c = {c}')
101
102
plt.xlabel('Radius (kpc)')
103
plt.ylabel('Density ($M_\\odot$/kpc$^3$)')
104
plt.title('NFW Dark Matter Density Profile')
105
plt.legend()
106
plt.grid(True, alpha=0.3, which='both')
107
plt.tight_layout()
108
plt.savefig('nfw_profile.pdf', dpi=150, bbox_inches='tight')
109
plt.close()
110
\end{pycode}
111
112
\begin{figure}[H]
113
\centering
114
\includegraphics[width=0.9\textwidth]{nfw_profile.pdf}
115
\caption{NFW density profiles for different concentrations.}
116
\end{figure}
117
118
\section{Tully-Fisher Relation}
119
120
$M_B = a \log_{10} V_{max} + b$
121
122
\begin{pycode}
123
# Generate mock data
124
np.random.seed(42)
125
V_max = np.random.uniform(100, 300, 50)
126
M_B = -7.5 * np.log10(V_max) + 3.5 + np.random.normal(0, 0.3, 50)
127
128
fig, ax = plt.subplots(figsize=(10, 6))
129
ax.scatter(np.log10(V_max), M_B, alpha=0.7)
130
# Fit line
131
coeffs = np.polyfit(np.log10(V_max), M_B, 1)
132
V_fit = np.linspace(100, 300, 100)
133
ax.plot(np.log10(V_fit), np.polyval(coeffs, np.log10(V_fit)), 'r-', linewidth=2)
134
ax.set_xlabel('log$_{10}$ $V_{max}$ (km/s)')
135
ax.set_ylabel('$M_B$ (mag)')
136
ax.set_title('Tully-Fisher Relation')
137
ax.invert_yaxis()
138
ax.grid(True, alpha=0.3)
139
plt.tight_layout()
140
plt.savefig('tully_fisher.pdf', dpi=150, bbox_inches='tight')
141
plt.close()
142
\end{pycode}
143
144
\begin{figure}[H]
145
\centering
146
\includegraphics[width=0.9\textwidth]{tully_fisher.pdf}
147
\caption{Tully-Fisher relation for spiral galaxies.}
148
\end{figure}
149
150
\section{Dark Matter Fraction}
151
152
\begin{pycode}
153
r_frac = np.linspace(0.1, 30, 100)
154
M_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))
155
x_frac = r_frac / r_s
156
M_dm = M_h * (np.log(1 + x_frac) - x_frac/(1 + x_frac)) / (np.log(1 + c) - c/(1 + c))
157
f_dm = M_dm / (M_dm + M_baryon)
158
159
fig, ax = plt.subplots(figsize=(10, 6))
160
ax.plot(r_frac, f_dm, 'b-', linewidth=2)
161
ax.axhline(y=0.5, color='r', linestyle='--')
162
ax.set_xlabel('Radius (kpc)')
163
ax.set_ylabel('Dark Matter Fraction')
164
ax.set_title('Enclosed Dark Matter Fraction')
165
ax.grid(True, alpha=0.3)
166
ax.set_xlim([0, 30])
167
ax.set_ylim([0, 1])
168
plt.tight_layout()
169
plt.savefig('dm_fraction.pdf', dpi=150, bbox_inches='tight')
170
plt.close()
171
\end{pycode}
172
173
\begin{figure}[H]
174
\centering
175
\includegraphics[width=0.9\textwidth]{dm_fraction.pdf}
176
\caption{Dark matter fraction vs radius.}
177
\end{figure}
178
179
\section{Velocity Dispersion}
180
181
\begin{pycode}
182
# Stellar velocity dispersion profile
183
r_sigma = np.linspace(0.1, 10, 100)
184
sigma_0 = 200 # km/s
185
r_e = 2 # Effective radius
186
sigma = sigma_0 * (1 + r_sigma / r_e)**(-0.5)
187
188
fig, ax = plt.subplots(figsize=(10, 6))
189
ax.plot(r_sigma, sigma, 'b-', linewidth=2)
190
ax.set_xlabel('Radius (kpc)')
191
ax.set_ylabel('Velocity Dispersion (km/s)')
192
ax.set_title('Stellar Velocity Dispersion Profile')
193
ax.grid(True, alpha=0.3)
194
plt.tight_layout()
195
plt.savefig('velocity_dispersion.pdf', dpi=150, bbox_inches='tight')
196
plt.close()
197
\end{pycode}
198
199
\begin{figure}[H]
200
\centering
201
\includegraphics[width=0.9\textwidth]{velocity_dispersion.pdf}
202
\caption{Velocity dispersion profile.}
203
\end{figure}
204
205
\section{Mass Modeling}
206
207
\begin{pycode}
208
# Enclosed mass
209
M_enc = (v_total * r)**2 / (G * r) * r
210
211
fig, ax = plt.subplots(figsize=(10, 6))
212
ax.semilogy(r, M_enc, 'b-', linewidth=2)
213
ax.set_xlabel('Radius (kpc)')
214
ax.set_ylabel('Enclosed Mass ($M_\\odot$)')
215
ax.set_title('Enclosed Mass Profile')
216
ax.grid(True, alpha=0.3, which='both')
217
plt.tight_layout()
218
plt.savefig('enclosed_mass.pdf', dpi=150, bbox_inches='tight')
219
plt.close()
220
\end{pycode}
221
222
\begin{figure}[H]
223
\centering
224
\includegraphics[width=0.9\textwidth]{enclosed_mass.pdf}
225
\caption{Enclosed mass profile.}
226
\end{figure}
227
228
\section{Results}
229
230
\begin{pycode}
231
v_max = np.max(v_total)
232
r_max = r[np.argmax(v_total)]
233
print(r'\begin{table}[H]')
234
print(r'\centering')
235
print(r'\caption{Galaxy Model Parameters}')
236
print(r'\begin{tabular}{@{}lc@{}}')
237
print(r'\toprule')
238
print(r'Property & Value \\')
239
print(r'\midrule')
240
print(f'Maximum velocity & {v_max:.0f} km/s \\\\')
241
print(f'Radius at $V_{{max}}$ & {r_max:.1f} kpc \\\\')
242
print(f'Bulge mass & {M_b:.1e} $M_\\odot$ \\\\')
243
print(f'Disk mass & {M_d:.1e} $M_\\odot$ \\\\')
244
print(f'Halo mass & {M_h:.1e} $M_\\odot$ \\\\')
245
print(r'\bottomrule')
246
print(r'\end{tabular}')
247
print(r'\end{table}')
248
\end{pycode}
249
250
\section{Conclusions}
251
252
Galaxy rotation curves require dark matter halos to explain observations.
253
254
\end{document}
255
256