Climate changes result from changes to the energy balance of the planet (or radiative forcings), due to e.g.:
greenhouse gas emissions (which trap radiation, warming the planet);
aerosol emissions from air pollution or volcanic eruptions (which block incoming radiation, cooling the planet);
changes to the solar cycle (which can increase or decrease the incoming solar radiation).
Historical Radiative Forcing
Code
# Dataset from https://zenodo.org/record/3973015# The CSV is read into a DataFrame object, and we specify that it is comma delimitedforcings_all_85 = CSV.read("data/climate/ERF_ssp585_1750-2500.csv", DataFrame, delim=",")# Separate out the individual componentsforcing_co2_85 = forcings_all_85[!,"co2"]# Get total aerosol forcingsforcing_aerosol_rad_85 = forcings_all_85[!,"aerosol-radiation_interactions"]forcing_aerosol_cloud_85 = forcings_all_85[!,"aerosol-cloud_interactions"]forcing_aerosol_85 = forcing_aerosol_rad_85 + forcing_aerosol_cloud_85forcing_total_85 = forcings_all_85[!,"total"]forcing_non_aerosol_85 = forcing_total_85 - forcing_aerosol_85forcing_other_85 = forcing_total_85 - (forcing_co2_85 + forcing_aerosol_85)t = time_forcing =Int64.(forcings_all_85[!,"year"]) # Ensure that years are interpreted as integersplot(xlabel="Year", ylabel="Radiative Forcing (W/m²)", tickfontsize=16, guidefontsize=18, legendfontsize=16, leftmargin=10mm, bottommargin=5mm, right_margin=5mm)plot!(time_forcing, forcing_total_85, label="Total", color=:black, linewidth=3)plot!(time_forcing, forcing_co2_85, label="CO₂", color=:orange, linewidth=2)plot!(time_forcing, forcing_aerosol_85, label="Aerosol", color=:blue, linewidth=2)plot!(time_forcing, forcing_other_85, label="Other", color=:purple, linewidth=2)plot!(size=(800, 450))xlims!((1750, 2020))ylims!(-4.5, 5)
Figure 2: Historical and projected radiative forcings.
Idea: Find best estimates\(\theta^*\) of model parameters \(\theta\) by minimizing the mismatch between data and simulations (denote by \(\mathbf{y} = F(\theta)\)).
Can you think of some common loss functions? What do they imply about how to penalize model error?
Programming Implementation
# use default values of S=3.2°C, d=100m, α=1.3functionebm(rf_nonaerosol, rf_aerosol; p=(3.2, 100, 1.3))# set up model parameters S, d, α = p # this unpacks the parameter tuple into variables F2xCO₂ =4.0# radiative forcing [W/m²] for a doubling of CO₂ λ = F2xCO₂ / S c =4.184e6# heat capacity/area [J/K/m²] C = c*d # heat capacity of mixed layer (per area) F = rf_nonaerosol + α*rf_aerosol # radiative forcing Δt =31558152. # annual timestep [s] T =zero(F)for i in1:length(F)-1 T[i+1] = T[i] + (F[i] - λ*T[i])/C * Δtend# return after normalizing to reference periodreturn T .-mean(T[1:20])end
Model Evaluation (Default Parameters)
Code
# generate simulationssim_years =1850:2020# model years to simulateidx =indexin(sim_years, t) # find indices in t vector of simulation years# since we specified default values for p, those are used for the parameterstemp_default =ebm(forcing_non_aerosol_85[idx], forcing_aerosol_85[idx]) temp_obs = temp_obs[indexin(sim_years, time_obs)] # filter to simulated years for plottingtemp_obs = temp_obs .-mean(temp_obs[1:20]) # re-normalize to be consistent with the model# plot simulated output and dataplot(sim_years, temp_default, xlabel="Year", ylabel="Temperature Anomaly (°C)", color=:blue, label="Simulation", linewidth=3, tickfontsize=16, guidefontsize=18, legendfontsize=16, leftmargin=10mm, bottommargin=5mm, right_margin=5mm)scatter!(sim_years, temp_obs, color=:black, linewidth=2, fillalpha=0.2, label="Data")
Figure 3: Comparison of model simualtion with default parameters and data.
Fitting the EBM By Minimizing RMSE
# define RMSE functionrmse(y, x) =sqrt(mean((y .- x).^2))# define wrapper function to map parameters to model evaluationsebm_wrap(params) =ebm(forcing_non_aerosol_85[idx], forcing_aerosol_85[idx], p = params)# minimize RMSE within some range for each parameter# important to make everything a Float instead of an Int lower = [1.0, 50.0, 0.0]upper = [4.0, 150.0, 2.0]p0 = [2.0, 100.0, 1.0]result = Optim.optimize(params ->rmse(ebm_wrap(params), temp_obs), lower, upper, p0)θ = result.minimizerθ
The connection between statistical modeling and simulation modeling is developing a probability model for the residuals.
Statistical Interpretation of RMSE Minimization
Claim: Minimizing the (R)MSE is the same as maximizing likelihood assuming independent and identically-normally-distributed residuals (with known variance).