Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/climate-science/temperature_model.tex
51 views
unlisted
1
% Temperature Model Template
2
% Topics: Energy balance, radiative forcing, climate sensitivity, feedback analysis
3
% Style: Research article with model validation
4
5
\documentclass[a4paper, 11pt]{article}
6
\usepackage[utf8]{inputenc}
7
\usepackage[T1]{fontenc}
8
\usepackage{amsmath, amssymb}
9
\usepackage{graphicx}
10
\usepackage{siunitx}
11
\usepackage{booktabs}
12
\usepackage{subcaption}
13
\usepackage[makestderr]{pythontex}
14
15
% Theorem environments
16
\newtheorem{definition}{Definition}[section]
17
\newtheorem{theorem}{Theorem}[section]
18
\newtheorem{example}{Example}[section]
19
\newtheorem{remark}{Remark}[section]
20
21
\title{Global Temperature Modeling: Energy Balance and Climate Sensitivity}
22
\author{Climate Dynamics Research Group}
23
\date{\today}
24
25
\begin{document}
26
\maketitle
27
28
\begin{abstract}
29
This study presents energy balance models for global mean surface temperature,
30
examining radiative forcing from greenhouse gases and the response of the climate system.
31
We analyze zero-dimensional and one-dimensional models, calculate climate sensitivity
32
from different feedback mechanisms, and compare model projections with observations.
33
The analysis quantifies transient and equilibrium climate response to CO$_2$ forcing.
34
\end{abstract}
35
36
\section{Introduction}
37
38
Earth's global mean surface temperature is determined by the balance between incoming
39
solar radiation and outgoing longwave radiation. Perturbations to this balance from
40
greenhouse gas increases lead to warming until a new equilibrium is reached.
41
42
\begin{definition}[Radiative Forcing]
43
Radiative forcing $F$ is the change in net radiative flux at the tropopause due to
44
a change in an external driver. For CO$_2$:
45
\begin{equation}
46
F = 5.35 \ln\left(\frac{C}{C_0}\right) \quad \text{W/m}^2
47
\end{equation}
48
where $C$ is CO$_2$ concentration and $C_0$ is the reference (pre-industrial) value.
49
\end{definition}
50
51
\section{Theoretical Framework}
52
53
\subsection{Zero-Dimensional Energy Balance}
54
55
\begin{theorem}[Planetary Energy Balance]
56
The rate of change of Earth's heat content is:
57
\begin{equation}
58
C_p \frac{dT}{dt} = F - \lambda \Delta T
59
\end{equation}
60
where $C_p$ is heat capacity, $F$ is radiative forcing, $\lambda$ is the climate
61
feedback parameter, and $\Delta T = T - T_0$ is the temperature anomaly.
62
\end{theorem}
63
64
\begin{definition}[Climate Sensitivity]
65
Equilibrium climate sensitivity (ECS) is the warming for doubled CO$_2$:
66
\begin{equation}
67
\text{ECS} = \frac{F_{2\times\text{CO}_2}}{\lambda} = \frac{3.7}{\lambda} \quad \text{K}
68
\end{equation}
69
With $\lambda \approx 1.2$ W/(m$^2$K), ECS $\approx$ 3 K.
70
\end{definition}
71
72
\subsection{Climate Feedbacks}
73
74
\begin{theorem}[Feedback Analysis]
75
The total feedback parameter is the sum of individual feedbacks:
76
\begin{equation}
77
\lambda = \lambda_0 + \lambda_{WV} + \lambda_{LR} + \lambda_A + \lambda_C
78
\end{equation}
79
where $\lambda_0$ is the Planck response (no feedbacks), and other terms are water
80
vapor, lapse rate, albedo, and cloud feedbacks.
81
\end{theorem}
82
83
\begin{remark}[Feedback Values]
84
Typical feedback values (W m$^{-2}$ K$^{-1}$):
85
\begin{itemize}
86
\item Planck (blackbody): $\lambda_0 \approx 3.2$ (negative, stabilizing)
87
\item Water vapor: $\lambda_{WV} \approx -1.8$ (positive, amplifying)
88
\item Lapse rate: $\lambda_{LR} \approx 0.6$ (negative)
89
\item Albedo: $\lambda_A \approx -0.3$ (positive)
90
\item Cloud: $\lambda_C \approx -0.5$ (positive, uncertain)
91
\end{itemize}
92
Net: $\lambda \approx 1.2$ W/(m$^2$K)
93
\end{remark}
94
95
\subsection{Transient Climate Response}
96
97
\begin{definition}[TCR and ECS]
98
\begin{itemize}
99
\item \textbf{Transient Climate Response (TCR)}: Warming at time of CO$_2$ doubling
100
under 1\%/yr increase ($\sim$70 years)
101
\item \textbf{Equilibrium Climate Sensitivity (ECS)}: Final equilibrium warming
102
for doubled CO$_2$
103
\end{itemize}
104
Typically TCR/ECS $\approx$ 0.5--0.7 due to ocean heat uptake.
105
\end{definition}
106
107
\section{Computational Analysis}
108
109
\begin{pycode}
110
import numpy as np
111
import matplotlib.pyplot as plt
112
from scipy.integrate import odeint
113
114
np.random.seed(42)
115
116
# Energy balance model
117
def ebm_single(T, t, F_func, C_eff, lambda_val):
118
F = F_func(t)
119
dTdt = (F - lambda_val * T) / C_eff
120
return dTdt
121
122
# Two-box model (surface + deep ocean)
123
def ebm_twobox(y, t, F_func, C_s, C_d, lambda_val, gamma):
124
T_s, T_d = y
125
F = F_func(t)
126
dTs = (F - lambda_val * T_s - gamma * (T_s - T_d)) / C_s
127
dTd = gamma * (T_s - T_d) / C_d
128
return [dTs, dTd]
129
130
# Parameters
131
C_eff = 10.0 # Effective heat capacity (W yr m^-2 K^-1)
132
C_s = 8.0 # Surface layer
133
C_d = 100.0 # Deep ocean
134
lambda_val = 1.2 # Climate feedback (W m^-2 K^-1)
135
gamma = 0.5 # Ocean heat exchange
136
137
# Forcing scenarios
138
CO2_pi = 280 # Pre-industrial CO2 (ppm)
139
140
def forcing_step(t):
141
"""Step doubling of CO2"""
142
return 3.7 if t > 0 else 0
143
144
def forcing_ramp(t):
145
"""1%/yr CO2 increase"""
146
if t < 0:
147
return 0
148
elif t < 70:
149
return 5.35 * np.log(1.01**t)
150
else:
151
return 5.35 * np.log(2)
152
153
def forcing_historical(t):
154
"""Simplified historical forcing"""
155
if t < 1850:
156
return 0
157
elif t < 2020:
158
CO2 = 280 * np.exp(0.004 * (t - 1850))
159
return 5.35 * np.log(CO2 / 280)
160
else:
161
return 3.0
162
163
def forcing_rcp(t, scenario='4.5'):
164
"""RCP scenario forcing"""
165
F_2020 = 3.0
166
if t < 2020:
167
return forcing_historical(t)
168
if scenario == '2.6':
169
return F_2020 + 0.5 * (1 - np.exp(-0.05 * (t - 2020)))
170
elif scenario == '4.5':
171
return F_2020 + 1.5 * (1 - np.exp(-0.03 * (t - 2020)))
172
else: # 8.5
173
return F_2020 + 0.08 * (t - 2020)
174
175
# Time arrays
176
t_step = np.linspace(-10, 200, 500)
177
t_ramp = np.linspace(-10, 140, 500)
178
t_hist = np.linspace(1850, 2100, 251)
179
180
# Solve step response
181
T_step = odeint(ebm_single, 0, t_step, args=(forcing_step, C_eff, lambda_val))[:, 0]
182
y0_2box = [0, 0]
183
T_2box_step = odeint(ebm_twobox, y0_2box, t_step,
184
args=(forcing_step, C_s, C_d, lambda_val, gamma))
185
186
# Solve ramp response
187
T_ramp = odeint(ebm_single, 0, t_ramp, args=(forcing_ramp, C_eff, lambda_val))[:, 0]
188
T_2box_ramp = odeint(ebm_twobox, y0_2box, t_ramp,
189
args=(forcing_ramp, C_s, C_d, lambda_val, gamma))
190
191
# Historical simulation
192
T_hist = odeint(ebm_single, 0, t_hist,
193
args=(lambda t: forcing_historical(t), C_eff, lambda_val))[:, 0]
194
195
# RCP scenarios
196
T_rcp26 = odeint(ebm_single, 0, t_hist,
197
args=(lambda t: forcing_rcp(t, '2.6'), C_eff, lambda_val))[:, 0]
198
T_rcp45 = odeint(ebm_single, 0, t_hist,
199
args=(lambda t: forcing_rcp(t, '4.5'), C_eff, lambda_val))[:, 0]
200
T_rcp85 = odeint(ebm_single, 0, t_hist,
201
args=(lambda t: forcing_rcp(t, '8.5'), C_eff, lambda_val))[:, 0]
202
203
# Climate sensitivity calculation
204
ECS = 3.7 / lambda_val
205
TCR = T_ramp[np.argmin(np.abs(t_ramp - 70))]
206
207
# Feedback analysis
208
lambda_0 = 3.2 # Planck
209
lambda_wv = -1.8 # Water vapor
210
lambda_lr = 0.6 # Lapse rate
211
lambda_a = -0.3 # Albedo
212
lambda_c = -0.5 # Cloud
213
feedbacks = {
214
'Planck': lambda_0,
215
'Water vapor': lambda_wv,
216
'Lapse rate': lambda_lr,
217
'Albedo': lambda_a,
218
'Cloud': lambda_c
219
}
220
lambda_total = sum(feedbacks.values())
221
222
# ECS uncertainty range
223
lambda_range = np.linspace(0.8, 2.0, 100)
224
ECS_range = 3.7 / lambda_range
225
226
# Create figure
227
fig = plt.figure(figsize=(14, 12))
228
229
# Plot 1: Step response
230
ax1 = fig.add_subplot(3, 3, 1)
231
ax1.plot(t_step, T_step, 'b-', linewidth=2, label='1-box')
232
ax1.plot(t_step, T_2box_step[:, 0], 'r-', linewidth=2, label='2-box surface')
233
ax1.plot(t_step, T_2box_step[:, 1], 'r--', linewidth=1.5, label='2-box deep')
234
ax1.axhline(y=ECS, color='gray', linestyle='--', alpha=0.7, label=f'ECS = {ECS:.1f} K')
235
ax1.set_xlabel('Time (years)')
236
ax1.set_ylabel('$\\Delta T$ (K)')
237
ax1.set_title('Step Response (2xCO$_2$)')
238
ax1.legend(fontsize=7)
239
ax1.set_xlim([-10, 200])
240
241
# Plot 2: Ramp response
242
ax2 = fig.add_subplot(3, 3, 2)
243
ax2.plot(t_ramp, T_ramp, 'b-', linewidth=2, label='Temperature')
244
forcing_ramp_arr = np.array([forcing_ramp(t) for t in t_ramp])
245
ax2_twin = ax2.twinx()
246
ax2_twin.plot(t_ramp, forcing_ramp_arr, 'r--', linewidth=1.5, label='Forcing')
247
ax2.axvline(x=70, color='gray', linestyle=':', alpha=0.7)
248
ax2.scatter([70], [TCR], s=100, c='green', zorder=5, label=f'TCR = {TCR:.2f} K')
249
ax2.set_xlabel('Time (years)')
250
ax2.set_ylabel('$\\Delta T$ (K)', color='b')
251
ax2_twin.set_ylabel('Forcing (W/m$^2$)', color='r')
252
ax2.set_title('1\\%/yr CO$_2$ Increase')
253
ax2.legend(fontsize=8, loc='upper left')
254
255
# Plot 3: Historical + projections
256
ax3 = fig.add_subplot(3, 3, 3)
257
ax3.plot(t_hist, T_hist, 'k-', linewidth=2, label='Historical')
258
ax3.plot(t_hist, T_rcp26, 'g-', linewidth=2, label='RCP 2.6')
259
ax3.plot(t_hist, T_rcp45, 'b-', linewidth=2, label='RCP 4.5')
260
ax3.plot(t_hist, T_rcp85, 'r-', linewidth=2, label='RCP 8.5')
261
ax3.axhline(y=1.5, color='orange', linestyle=':', label='1.5 K')
262
ax3.axhline(y=2.0, color='red', linestyle=':', label='2.0 K')
263
ax3.set_xlabel('Year')
264
ax3.set_ylabel('$\\Delta T$ (K)')
265
ax3.set_title('Temperature Projections')
266
ax3.legend(fontsize=7, loc='upper left')
267
268
# Plot 4: Feedback analysis
269
ax4 = fig.add_subplot(3, 3, 4)
270
names = list(feedbacks.keys())
271
values = list(feedbacks.values())
272
colors = ['gray', 'blue', 'cyan', 'orange', 'purple']
273
bars = ax4.barh(names, values, color=colors)
274
ax4.axvline(x=0, color='black', linewidth=0.5)
275
ax4.set_xlabel('Feedback (W m$^{-2}$ K$^{-1}$)')
276
ax4.set_title(f'Feedback Components ($\\lambda_{{total}}$ = {lambda_total:.1f})')
277
278
# Plot 5: ECS distribution
279
ax5 = fig.add_subplot(3, 3, 5)
280
ax5.plot(lambda_range, ECS_range, 'b-', linewidth=2)
281
ax5.axhline(y=3.0, color='red', linestyle='--', alpha=0.7, label='Best estimate')
282
ax5.fill_between([1.0, 1.5], 0, 6, alpha=0.2, color='green', label='Likely range')
283
ax5.set_xlabel('$\\lambda$ (W m$^{-2}$ K$^{-1}$)')
284
ax5.set_ylabel('ECS (K)')
285
ax5.set_title('ECS vs Feedback Parameter')
286
ax5.legend(fontsize=8)
287
ax5.set_ylim([0, 6])
288
289
# Plot 6: Warming rate
290
ax6 = fig.add_subplot(3, 3, 6)
291
dT_dt = np.diff(T_hist) / np.diff(t_hist)
292
ax6.plot(t_hist[1:], dT_dt * 10, 'b-', linewidth=1.5) # per decade
293
ax6.set_xlabel('Year')
294
ax6.set_ylabel('Warming rate (K/decade)')
295
ax6.set_title('Rate of Temperature Change')
296
297
# Plot 7: Ocean heat uptake
298
ax7 = fig.add_subplot(3, 3, 7)
299
ax7.plot(t_step, T_2box_step[:, 0] - T_2box_step[:, 1], 'purple', linewidth=2)
300
ax7.set_xlabel('Time (years)')
301
ax7.set_ylabel('$T_s - T_d$ (K)')
302
ax7.set_title('Surface-Deep Ocean Temperature Difference')
303
304
# Plot 8: Forcing components
305
ax8 = fig.add_subplot(3, 3, 8)
306
# Different forcing agents (simplified)
307
t_forcing = np.linspace(1850, 2020, 100)
308
CO2_forcing = 5.35 * np.log(280 * np.exp(0.004 * (t_forcing - 1850)) / 280)
309
CH4_forcing = 0.3 * (1 - np.exp(-0.01 * (t_forcing - 1850)))
310
aerosol_forcing = -0.5 * (1 - np.exp(-0.02 * (t_forcing - 1850)))
311
ax8.plot(t_forcing, CO2_forcing, 'r-', linewidth=2, label='CO$_2$')
312
ax8.plot(t_forcing, CH4_forcing, 'g-', linewidth=2, label='CH$_4$')
313
ax8.plot(t_forcing, aerosol_forcing, 'b-', linewidth=2, label='Aerosols')
314
ax8.plot(t_forcing, CO2_forcing + CH4_forcing + aerosol_forcing, 'k--',
315
linewidth=2, label='Total')
316
ax8.set_xlabel('Year')
317
ax8.set_ylabel('Forcing (W/m$^2$)')
318
ax8.set_title('Radiative Forcing Components')
319
ax8.legend(fontsize=8)
320
321
# Plot 9: Energy imbalance
322
ax9 = fig.add_subplot(3, 3, 9)
323
F_arr = np.array([forcing_historical(t) for t in t_hist])
324
N = F_arr - lambda_val * T_hist # Net energy imbalance
325
ax9.plot(t_hist, N, 'b-', linewidth=2)
326
ax9.axhline(y=0, color='black', linewidth=0.5)
327
ax9.set_xlabel('Year')
328
ax9.set_ylabel('N (W/m$^2$)')
329
ax9.set_title('Planetary Energy Imbalance')
330
ax9.fill_between(t_hist, 0, N, where=N > 0, alpha=0.3, color='red', label='Heating')
331
ax9.legend(fontsize=8)
332
333
plt.tight_layout()
334
plt.savefig('temperature_model_analysis.pdf', dpi=150, bbox_inches='tight')
335
plt.close()
336
337
# Key results
338
T_2020 = T_hist[np.argmin(np.abs(t_hist - 2020))]
339
T_2100_rcp45 = T_rcp45[-1]
340
\end{pycode}
341
342
\begin{figure}[htbp]
343
\centering
344
\includegraphics[width=\textwidth]{temperature_model_analysis.pdf}
345
\caption{Climate temperature modeling: (a) Step response to CO$_2$ doubling; (b) Ramp
346
response showing TCR; (c) Historical and projected temperatures; (d) Feedback component
347
analysis; (e) ECS dependence on feedback parameter; (f) Warming rate over time;
348
(g) Ocean heat uptake dynamics; (h) Radiative forcing components; (i) Planetary energy
349
imbalance.}
350
\label{fig:temperature}
351
\end{figure}
352
353
\section{Results}
354
355
\subsection{Climate Sensitivity}
356
357
\begin{pycode}
358
print(r"\begin{table}[htbp]")
359
print(r"\centering")
360
print(r"\caption{Climate Sensitivity Parameters}")
361
print(r"\begin{tabular}{lcc}")
362
print(r"\toprule")
363
print(r"Parameter & Value & Units \\")
364
print(r"\midrule")
365
print(f"Feedback parameter $\\lambda$ & {lambda_val} & W m$^{{-2}}$ K$^{{-1}}$ \\\\")
366
print(f"Equilibrium Climate Sensitivity & {ECS:.1f} & K \\\\")
367
print(f"Transient Climate Response & {TCR:.2f} & K \\\\")
368
print(f"TCR/ECS ratio & {TCR/ECS:.2f} & --- \\\\")
369
print(r"\bottomrule")
370
print(r"\end{tabular}")
371
print(r"\label{tab:sensitivity}")
372
print(r"\end{table}")
373
\end{pycode}
374
375
\subsection{Temperature Projections}
376
377
\begin{pycode}
378
print(r"\begin{table}[htbp]")
379
print(r"\centering")
380
print(r"\caption{Projected Temperature Changes}")
381
print(r"\begin{tabular}{lcc}")
382
print(r"\toprule")
383
print(r"Scenario & 2100 $\Delta T$ (K) & Exceeds 2 K? \\")
384
print(r"\midrule")
385
print(f"RCP 2.6 & {T_rcp26[-1]:.1f} & {'No' if T_rcp26[-1] < 2 else 'Yes'} \\\\")
386
print(f"RCP 4.5 & {T_rcp45[-1]:.1f} & {'No' if T_rcp45[-1] < 2 else 'Yes'} \\\\")
387
print(f"RCP 8.5 & {T_rcp85[-1]:.1f} & {'No' if T_rcp85[-1] < 2 else 'Yes'} \\\\")
388
print(r"\bottomrule")
389
print(r"\end{tabular}")
390
print(r"\label{tab:projections}")
391
print(r"\end{table}")
392
\end{pycode}
393
394
\section{Discussion}
395
396
\begin{example}[Equilibrium vs Transient Response]
397
The TCR of $\py{f"{TCR:.2f}"}$ K is smaller than the ECS of $\py{f"{ECS:.1f}"}$ K because
398
the deep ocean absorbs heat. The ratio TCR/ECS = $\py{f"{TCR/ECS:.2f}"}$ indicates that
399
only $\sim$\py{f"{TCR/ECS*100:.0f}"}\% of equilibrium warming is realized at the time
400
of CO$_2$ doubling.
401
\end{example}
402
403
\begin{remark}[Feedback Uncertainty]
404
Cloud feedback remains the largest source of uncertainty in ECS estimates. Positive
405
cloud feedback (reduced low clouds with warming) increases ECS, while negative feedback
406
decreases it. Current estimates range from $-0.2$ to $-1.2$ W m$^{-2}$ K$^{-1}$.
407
\end{remark}
408
409
\begin{example}[Committed Warming]
410
Even if emissions stop, warming continues due to:
411
\begin{itemize}
412
\item Ocean thermal inertia (decades to equilibrate)
413
\item Reduction in aerosol cooling (immediate)
414
\item Carbon cycle feedbacks (decades to centuries)
415
\end{itemize}
416
This "committed warming" adds $\sim$0.5 K to current warming.
417
\end{example}
418
419
\section{Conclusions}
420
421
This temperature modeling analysis demonstrates:
422
\begin{enumerate}
423
\item ECS is $\py{f"{ECS:.1f}"}$ K with feedback parameter $\lambda = \py{f"{lambda_val}"}$ W m$^{-2}$ K$^{-1}$
424
\item TCR is $\py{f"{TCR:.2f}"}$ K, approximately \py{f"{TCR/ECS*100:.0f}"}\% of ECS
425
\item Current warming is $\sim$\py{f"{T_2020:.1f}"} K above pre-industrial
426
\item RCP 4.5 projects $\py{f"{T_2100_rcp45:.1f}"}$ K warming by 2100
427
\item Water vapor and cloud feedbacks dominate sensitivity uncertainty
428
\end{enumerate}
429
430
\section*{Further Reading}
431
432
\begin{itemize}
433
\item Hartmann, D.L. \textit{Global Physical Climatology}, 2nd ed. Elsevier, 2016.
434
\item Held, I.M. \& Soden, B.J. Water vapor feedback and global warming. \textit{Annu. Rev. Energy Environ.} 25, 441--475, 2000.
435
\item Sherwood, S.C. et al. An assessment of Earth's climate sensitivity using multiple lines of evidence. \textit{Rev. Geophys.} 58, e2019RG000678, 2020.
436
\end{itemize}
437
438
\end{document}
439
440