Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/atmospheric-science/air_pollution.tex
51 views
unlisted
1
\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}
13
14
\title{Air Pollution Dispersion\\Gaussian Plume Modeling}
15
\author{Environmental Engineering Department}
16
\date{\today}
17
18
\begin{document}
19
\maketitle
20
21
\begin{abstract}
22
Computational analysis of air pollution dispersion using Gaussian plume models and deposition calculations.
23
\end{abstract}
24
25
26
\section{Introduction}
27
28
Air pollution dispersion models predict pollutant concentrations downwind of emission sources.
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
\end{pycode}
36
37
\section{Gaussian Plume Model}
38
39
$C(x,y,z) = \frac{Q}{2\pi u \sigma_y \sigma_z} \exp\left(-\frac{y^2}{2\sigma_y^2}\right) \left[\exp\left(-\frac{(z-H)^2}{2\sigma_z^2}\right) + \exp\left(-\frac{(z+H)^2}{2\sigma_z^2}\right)\right]$
40
41
\begin{pycode}
42
def gaussian_plume(x, y, z, Q, u, H, stability='D'):
43
# Pasquill-Gifford dispersion parameters
44
if stability == 'A':
45
a_y, b_y, a_z, b_z = 0.22, 0.894, 0.20, 1.0
46
elif stability == 'D':
47
a_y, b_y, a_z, b_z = 0.08, 0.894, 0.06, 0.911
48
elif stability == 'F':
49
a_y, b_y, a_z, b_z = 0.04, 0.894, 0.016, 0.75
50
51
sigma_y = a_y * x**b_y
52
sigma_z = a_z * x**b_z
53
54
C = Q / (2 * np.pi * u * sigma_y * sigma_z) * \
55
np.exp(-y**2 / (2 * sigma_y**2)) * \
56
(np.exp(-(z - H)**2 / (2 * sigma_z**2)) + np.exp(-(z + H)**2 / (2 * sigma_z**2)))
57
return C
58
59
# Parameters
60
Q = 100 # g/s emission rate
61
u = 5 # m/s wind speed
62
H = 50 # m stack height
63
64
x = np.linspace(100, 5000, 200)
65
C_ground = gaussian_plume(x, 0, 0, Q, u, H)
66
67
fig, ax = plt.subplots(figsize=(10, 6))
68
ax.semilogy(x/1000, C_ground * 1e6, 'b-', linewidth=2)
69
ax.set_xlabel('Downwind Distance (km)')
70
ax.set_ylabel('Concentration ($\\mu$g/m$^3$)')
71
ax.set_title('Ground-Level Concentration')
72
ax.grid(True, alpha=0.3, which='both')
73
plt.tight_layout()
74
plt.savefig('plume_centerline.pdf', dpi=150, bbox_inches='tight')
75
plt.close()
76
\end{pycode}
77
78
\begin{figure}[H]
79
\centering
80
\includegraphics[width=0.85\textwidth]{plume_centerline.pdf}
81
\caption{Ground-level pollutant concentration along plume centerline.}
82
\end{figure}
83
84
\section{Stability Class Effects}
85
86
\begin{pycode}
87
fig, ax = plt.subplots(figsize=(10, 6))
88
for stab in ['A', 'D', 'F']:
89
C = gaussian_plume(x, 0, 0, Q, u, H, stability=stab)
90
ax.semilogy(x/1000, C * 1e6, linewidth=1.5, label=f'Class {stab}')
91
ax.set_xlabel('Downwind Distance (km)')
92
ax.set_ylabel('Concentration ($\\mu$g/m$^3$)')
93
ax.set_title('Effect of Atmospheric Stability')
94
ax.legend()
95
ax.grid(True, alpha=0.3, which='both')
96
plt.tight_layout()
97
plt.savefig('stability_effects.pdf', dpi=150, bbox_inches='tight')
98
plt.close()
99
\end{pycode}
100
101
\begin{figure}[H]
102
\centering
103
\includegraphics[width=0.85\textwidth]{stability_effects.pdf}
104
\caption{Concentration for different stability classes.}
105
\end{figure}
106
107
\section{2D Concentration Field}
108
109
\begin{pycode}
110
x_2d = np.linspace(100, 3000, 100)
111
y_2d = np.linspace(-500, 500, 100)
112
X, Y = np.meshgrid(x_2d, y_2d)
113
C_2d = gaussian_plume(X, Y, 0, Q, u, H)
114
115
fig, ax = plt.subplots(figsize=(12, 6))
116
cs = ax.contourf(X/1000, Y, C_2d * 1e6, levels=20, cmap='YlOrRd')
117
plt.colorbar(cs, label='Concentration ($\\mu$g/m$^3$)')
118
ax.set_xlabel('Downwind Distance (km)')
119
ax.set_ylabel('Crosswind Distance (m)')
120
ax.set_title('Ground-Level Concentration Field')
121
plt.tight_layout()
122
plt.savefig('concentration_field.pdf', dpi=150, bbox_inches='tight')
123
plt.close()
124
\end{pycode}
125
126
\begin{figure}[H]
127
\centering
128
\includegraphics[width=0.95\textwidth]{concentration_field.pdf}
129
\caption{2D ground-level concentration contours.}
130
\end{figure}
131
132
\section{Stack Height Effects}
133
134
\begin{pycode}
135
heights = [30, 50, 100, 150]
136
137
fig, ax = plt.subplots(figsize=(10, 6))
138
for H_s in heights:
139
C = gaussian_plume(x, 0, 0, Q, u, H_s)
140
ax.semilogy(x/1000, C * 1e6, linewidth=1.5, label=f'H = {H_s} m')
141
ax.set_xlabel('Downwind Distance (km)')
142
ax.set_ylabel('Concentration ($\\mu$g/m$^3$)')
143
ax.set_title('Effect of Stack Height')
144
ax.legend()
145
ax.grid(True, alpha=0.3, which='both')
146
plt.tight_layout()
147
plt.savefig('stack_height_effects.pdf', dpi=150, bbox_inches='tight')
148
plt.close()
149
\end{pycode}
150
151
\begin{figure}[H]
152
\centering
153
\includegraphics[width=0.85\textwidth]{stack_height_effects.pdf}
154
\caption{Ground concentration for different stack heights.}
155
\end{figure}
156
157
\section{Maximum Concentration}
158
159
\begin{pycode}
160
x_max = H * np.sqrt(2) # Approximate location of max
161
C_max = gaussian_plume(x, 0, 0, Q, u, H)
162
idx_max = np.argmax(C_max)
163
164
fig, ax = plt.subplots(figsize=(10, 6))
165
ax.plot(x/1000, C_max * 1e6, 'b-', linewidth=2)
166
ax.plot(x[idx_max]/1000, C_max[idx_max] * 1e6, 'ro', markersize=10)
167
ax.annotate(f'Max: {C_max[idx_max]*1e6:.1f} $\\mu$g/m$^3$\nat {x[idx_max]/1000:.1f} km',
168
xy=(x[idx_max]/1000, C_max[idx_max]*1e6), xytext=(x[idx_max]/1000 + 1, C_max[idx_max]*1e6 * 1.5),
169
arrowprops=dict(arrowstyle='->'))
170
ax.set_xlabel('Downwind Distance (km)')
171
ax.set_ylabel('Concentration ($\\mu$g/m$^3$)')
172
ax.set_title('Maximum Ground-Level Concentration')
173
ax.grid(True, alpha=0.3)
174
plt.tight_layout()
175
plt.savefig('maximum_concentration.pdf', dpi=150, bbox_inches='tight')
176
plt.close()
177
\end{pycode}
178
179
\begin{figure}[H]
180
\centering
181
\includegraphics[width=0.85\textwidth]{maximum_concentration.pdf}
182
\caption{Location and magnitude of maximum concentration.}
183
\end{figure}
184
185
\section{Vertical Profile}
186
187
\begin{pycode}
188
z_profile = np.linspace(0, 200, 100)
189
x_loc = 1000 # m
190
191
C_vertical = gaussian_plume(x_loc, 0, z_profile, Q, u, H)
192
193
fig, ax = plt.subplots(figsize=(8, 8))
194
ax.plot(C_vertical * 1e6, z_profile, 'b-', linewidth=2)
195
ax.axhline(y=H, color='r', linestyle='--', label=f'Stack height = {H} m')
196
ax.set_xlabel('Concentration ($\\mu$g/m$^3$)')
197
ax.set_ylabel('Height (m)')
198
ax.set_title(f'Vertical Profile at x = {x_loc} m')
199
ax.legend()
200
ax.grid(True, alpha=0.3)
201
plt.tight_layout()
202
plt.savefig('vertical_profile.pdf', dpi=150, bbox_inches='tight')
203
plt.close()
204
\end{pycode}
205
206
\begin{figure}[H]
207
\centering
208
\includegraphics[width=0.7\textwidth]{vertical_profile.pdf}
209
\caption{Vertical concentration profile.}
210
\end{figure}
211
212
\section{Results}
213
214
\begin{pycode}
215
x_max_dist = x[idx_max]
216
C_max_val = C_max[idx_max] * 1e6
217
218
print(r'\begin{table}[H]')
219
print(r'\centering')
220
print(r'\caption{Dispersion Model Results}')
221
print(r'\begin{tabular}{@{}lc@{}}')
222
print(r'\toprule')
223
print(r'Parameter & Value \\')
224
print(r'\midrule')
225
print(f'Emission rate & {Q} g/s \\\\')
226
print(f'Wind speed & {u} m/s \\\\')
227
print(f'Stack height & {H} m \\\\')
228
print(f'Max concentration & {C_max_val:.1f} $\\mu$g/m$^3$ \\\\')
229
print(f'Distance to max & {x_max_dist:.0f} m \\\\')
230
print(r'\bottomrule')
231
print(r'\end{tabular}')
232
print(r'\end{table}')
233
\end{pycode}
234
235
\section{Conclusions}
236
237
Gaussian plume models provide practical estimates of pollutant dispersion for regulatory applications.
238
239
240
\end{document}
241
242