The Variance of Absorption Spectra
Contents
The Variance of Absorption Spectra#
From discussing the mechanics of absorption spectra, it was clear that absorption lines do not have a constant magnitude for all temperatures and pressures. This section uses an approximate global atmosphere model to reproduce the atmosphere environment at different altitudes.
The nature of climate models is that they have many interlinked parameters. These relationships must be modelled when the goal is to produce the most accurate model possible. However, this project aims to build a reasonable approximation for pedagogy.
Standard Atmosphere Model#
The “US Standard Atmosphere, 1976”[OAA+76] provides pressure, temperature, and density vertical profiles. The model takes values which are roughly representative of year-round mid-latitude conditions. The density profile is calculated using the temperature and pressure profiles through the ideal gas equation
Where,
In addition to the atmospheres’ pressure and temperature changing the concentration of GHGs can change. A reasonable assumption in the troposphere, below
Despite falling density and pressure, there is an increase in temperature after
Click to show
atlittudes = np.linspace(0, 80000, 100)
temp = simpletrans.isa.get_temperature(atlittudes)
pressure = simpletrans.isa.get_pressure(atlittudes)
density = simpletrans.isa.get_density(atlittudes)
fig, ax = plt.subplots(1, 3, figsize=(10, 6), sharey=True)
labels = ["Temperature $(K)$", "Pressure $(Pa)$", "Density $(kg/m^3)$"]
for i, profile in enumerate([temp, pressure, density]):
ax[i].plot(profile, atlittudes, color=colours.durham.ink)
ax[i].fill_between(
[np.min(profile), np.max(profile)],
[0, 0],
[10**4, 10**4],
linestyle="--",
color=colours.durham.ink,
label="Troposphere",
alpha=0.2,
)
ax[i].set_yticks(ax[i].get_yticks(), ax[i].get_yticks() / 1000)
ax[i].set_ylim(0, 80000)
ax[i].set_xlabel(labels[i])
ax[0].set_ylabel("Altitude $(km)$")
ax[1].set_title("ISA Vertical Profile up to $10km$")
ax[0].legend();

The Variation of the Absorption Cross-section of #
The HITRAN Database provides the line-by-line intensities for more than 55 molecules. Using the IPCC reports data on the most potent greenhouse gases, the most impactful three are,
Befor devleloping the radiative transfer model, isolating the broadening behaviour is worthwhile. The changes in
Additionally, to temperature and pressure dependence on the broadening, there is a further temperature dependence on the line intensity due to the accessibility of a given transition. At low temperatures, high-energy transitions, those of low wavelength, are heavily suppressed as the molecules lack the energy to access either the excitation or vibrational mode. A Bose-Einstein distribution quantifies the availability of a transition. When the intensity of a transition is known for one temperature, the ratio of the probabilities gives the intensity
Where
In the figure below
In the figure broadening, effects can be seen with the high altitude peaks having a narrower line width than those of low altitude. However, the overall area of the peaks is largely similar. When calculating radiative transfer, the absorption coefficient determines where the absorption takes place. However, the absorption intensity is heavily dictated by the gas density along the light’s path. Optical depth characterises the amount of light scattered by a medium and is a combination of the abundance of the gas and its absorption coefficient.
"""
This code block demonstrates a simple query to the local database built by
the SimpleTrans package developed with the book. The path is to
The Database built by SimpleTrans. The next block provides the figure
plotting.
"""
path = "../Database/optical_depth.db"
conn = sqlite3.connect(path)
sql_query = "SELECT * FROM optical_depths WHERE mol_id = 2"
co2_optical_depth = pd.read_sql_query(sql_query, conn)
sql_query = "SELECT * FROM gases"
gases = pd.read_sql_query(sql_query, conn)
alts = co2_optical_depth["altitude"].unique();
Click to show
cmap = sns.color_palette("rocket", 10)
sm = plt.cm.ScalarMappable(
cmap="rocket", norm=plt.Normalize(vmin=0, vmax=10000)
)
fig, ax = plt.subplots(1, 1, figsize=(10, 6))
color_cycle = ax.set_prop_cycle(color=cmap)
for alt in alts:
if alt <= 9500:
mask = co2_optical_depth["altitude"] == alt
abs_coef = co2_optical_depth[mask]["abs_coef"]
nu = co2_optical_depth[mask]["wave_no"]
plot = ax.plot(nu, abs_coef, alpha=0.4)
cb = fig.colorbar(sm)
cb.set_label("Altitude (m)")
ax.set_xlim(635, 700)
ax.set_ylim(0, 9 * 10**-18)
ax.set_xlabel("Wavenumber $(cm^{-1})$")
ax.set_ylabel("Absorption Coefficient $(cm^2/molecule)$");

Optical Depth of #
When light is transmitted through the atmosphere, the optical depth](./radiative_transfer.ipynb) is the quantity of interest. This quantity is put into context in the next section.
The absorption coefficient,
Where
The transmission illustrates clearly in which regions the gas is opaque, which is useful for assessing how the optical behaviour of the gas changes with altitude.
Increasing Altitude’s effect on Absorption#
Because of the density decrease associated with an increase in altitude, the amount of radiation that is absorbed by molecules of
"""
We create two dictionaries below that store the ratio of total transmitted
flux, {\int transmission dwavnumber} / {\int dwavenumber}. In the
flux_ratios dictionary, the absorption coefficient varies with altitude,
flux_ratios_fixed_abs. This takes the absorption coefficient of CO2 at
500 m, and does not vary it while calculating the optical depth.
Additionally, the transmission function is sored in the flux ratio list.
"""
od = []
flux_ratios = []
transmission_fraction = {}
transmission_fraction_fixed_abs = {}
ac_500_mask = co2_optical_depth["altitude"] == 500
ac_500 = co2_optical_depth["abs_coef"][ac_500_mask]
for alt in alts:
if alt <= 9500:
mask = co2_optical_depth["altitude"] == alt
alt_od = co2_optical_depth["optical_depth"][mask]
od.append(alt_od)
flux_ratios.append(np.exp(-alt_od))
fixed_abs_coef_od = optical_depth(
alt - 500, alt + 500, 400, ac_500
)
x = co2_optical_depth["wave_no"][mask]
flux_ratios_fixed_ac = np.exp(-fixed_abs_coef_od)
transmission_fraction_fixed_abs[f"{alt}"] = simpson(
flux_ratios_fixed_ac, x
) / simpson(np.ones_like(x), x)
transmission_fraction[f"{alt}"] = simpson(
np.exp(-alt_od), co2_optical_depth["wave_no"][mask]
) / simpson(np.ones_like(x), x)
Click to show
result_frame = pd.DataFrame.from_dict(transmission_fraction, "index", columns=["Normal"])
result_frame["Fixed Absorption Coefficient"] = pd.DataFrame.from_dict(transmission_fraction_fixed_abs, "index")
result_frame
Normal | Fixed Absorption Coefficient | |
---|---|---|
500.0 | 0.892173 | 0.892635 |
1500.0 | 0.896595 | 0.894316 |
2500.0 | 0.901125 | 0.896050 |
3500.0 | 0.905758 | 0.897841 |
4500.0 | 0.910490 | 0.899694 |
5500.0 | 0.915317 | 0.901614 |
6500.0 | 0.920230 | 0.903605 |
7500.0 | 0.925168 | 0.905673 |
8500.0 | 0.930113 | 0.907822 |
9500.0 | 0.935077 | 0.910055 |
The above table shows a total transmission differential of order one percent when not including broadening in the CO2 spectrum. This is significant enough that the radiation transfer model must be able to include this variation.
The figure below plots the ratio of spectral radiance transmitted over the outgoing longwave wavenumber spectrum. The colour bar shows the colour gradient associated with increasing altitude. The plot has the highest altitude plotted on the top layer, so if you can see any dark outlines, this indicates that there is reduced transmission at lower altitudes. Although, in many places, there appears to be a fill, this is just a function of the resolution of the plot and the line width. There are just many individual peaks, which, when plotted, merge.

Logarithmic Plot of Optical Depth, #
The previous figure displays clear windows of opacity which decrease in size with increasing altitude. By plotting a semilog plot of the optical depth
If one was deploying a radiative transfer model with stricter performance requirements, dropping values from the arrays, don’t contribute substantially to the transmission profile can improve speed. Alternatively, an absorption coefficient minimum threshold can be used. The semilog plot highlights the abundance of detail in regions where the transmission function is nearly transparent. In addition, if performance is even more of a concern, windowed averaging of areas of interest can also aid in reducing the number of computations, effectively reducing the resolution of the data.

Hopefully, at this point, you have some understanding about how to move from line-by-line data to absorption coefficents and how they vary with altitude. In the next section a simplified model of radiative transfer is explored.
Note
As you read on you may think that the implementation of broadening is deeply unecessary, and very expensinve, especially when the data is then binned. This was not properly planned and a comparison of the effect of broadening after binning is a worth while excercise, which has not been done due to time constraints.
This would be the first step in introducing an efficiency speed up as one could remove the database etc. However, implementing the SQL and database has real value in terms of teaching.