Reading for Lab #3 on Mon., Feb 7:
PDF version
Instructions for Lab #3: Infrared Light
Instructions
It would be good to print these instructions and bring them to lab on Monday, or else to have the PDF with the instructions handy during lab.
For these exercises, I recommend that you work on them with the interactive web-based MODTRAN models to get a feel for how the models apply to the exercise.
Once you are clear what you are doing, you can use the R scripts and RMarkdown to turn those insights into reproducible research.
Using MODTRAN with RMarkdown.
This RMarkdown document includes the line source("_scripts/modtran.R")
,
which loads a script with the following functions:
run_modtran()
allows you to automatically download a file with the data from a MODTRAN run. You call it with the following arguments:filename
is an optional name for a file to save the data to. If you don’t specify thefilename
, thenrun_modtran
will not save the model output to the disk. I recommend giving it a meaningful name: for instance, a run with 550 ppm CO2 and 3.4 ppm methane might be called “modtran_440_34.txt
”. Make up your own file names, but think about how you will tell which is which. I also recommend that you save the files in the_data
subdirectory to keep your project nicely organized.co2_ppm
is the amount of CO2 in parts per million. The default is 400.ch4_ppm
is the amount of methane in parts per million. The default is 1.7.trop_o3_ppb
is the amount of ozone in the troposphere, in parts per billion. The default is 28. You probably won’t change this unless you’re setting all greenhouse gases to zero.strat_o3_scale
is the amount of stratospheric ozone, relative to the naturally occurring levels in the ozone layer. You probably won’t change this unless you’re setting all greenhouse gases to zero.h2o_scale
is the amount of water vapor, relative to the naturally occurring levels in the atmosphere. You probably won’t change this unless you’re setting all greenhouse gases to zero.freon_scale
is the amount of freon chemicals (used for refrigerators and air conditioners), relative to the current amounts. You probably won’t change this unless you’re setting all greenhouse gases to zero.delta_t
is the temperature offset, in degrees C. You adjust this to restore radiative equilibrium after you change the amount of CO2 or other greenhouse gases.h2o_fixed
is what quantity to hold fixed for water vapor. Possible values are “vapor pressure” (the default), and “relative humidity”atmosphere
is the locality in the MODTRAN model. Possible values are:"tropical"
(the default),"midlatitude summer"
,"midlatitude winter"
,"subarctic summer"
,"subarctic winter"
,- and
"standard"
for the 1976 U.S. standard atmosphere.
clouds
is the specification of clouds and rain. Possible values are"none"
(the default),"cumulus"
,"altostratus"
,"stratus"
,"stratocumulus"
,"nimbostratus"
,"drizzle"
,"light rain"
,"medium rain"
,"heavy rain"
,"extreme rain"
,"standard cirrus"
,"subvisual cirrus"
,- and
"NOAA cirrus"
.
Stratus clouds are flat, opaque, and low-altitude. Altostratus clouds are flat and medium altitude. Cirrus clouds are thin and high-altitude. They are hard to model, so there are three different varieties. Cumulus clouds are thick and stretch from low altitudes to medium altitudes. Stratocumulus clouds are like thunder clouds. They are very tall and reach from low altitudes to the top of the troposphere. Nimbostratus clouds are low and thick, like stratus, but produce rain.
altitude_km
is the altitude, in kilometers above sea level, that you put your virtual sensor in the model. The default is 70 km, which is above almost all of the atmosphere.For some exercises, you may experiment with putting the sensor somewhere around 8 to 12 km, which is the top of the troposphere, below the stratospheric ozone layer.
For other exercises, you might want to put it at 0 km (ground level), and set it to look up instead of down, so you can see the IR radiation coming down to the ground from the atmosphere instead of looking at the IR radiation going out to space.
looking
is the direction the sensor is looking. The options are “down” (the default) or “up”.
Any arguments you don’t specify explicitly take on their default value. Thus,
run_modtran(file.path(data_dir, "modtran_experiment_1.txt"), co2_ppm = 800, delta_t = 1.0, h2o_fixed = "relative humidity")
would run with all the default values, except for 800 ppm CO2, a temperature offset of 1°C, and holding relative humidity fixed.The function returns a list with 7 elements:
spectrum
is a data tibble with the spectral information (wavelengthlambda
, wavenumberk
, outgoing IR intensitytk
, and a number of other variables.)profile
is the profile of the atmosphere: a tibble with seven columns:Z
is the altitude in km,P
is the atmospheric pressure, in millibars, andT
is the temperature in Kelvin.H2O
is the concentration of water vapor, in parts per million at each altitude.O3
is the concentration of ozone, in parts per million at each altitude.CO2
is the concentration of carbon dioxide, in parts per million at each altitude.CH4
is the concentration of methane, in parts per million at each altitude.
co2
is the atmospheric CO2 concentrationch4
is the atmospheric methane concentrationi_out
is the intensity of the outgoing IR radiation flux.t_ground
is the ground temperature (in Kelvin) used in the model run. (Remember that this is something you set when you run the model. MODTRAN cannot calculate the way ground temperature changes when you change greenhouse gases, clouds, or other characteristics of the atmosphere.)t_tropo
is the temperature at the tropopause (in Kelvin).h_tropo
is the height of the tropopause (in km).alt
is the altitude of the virtual sensor.sensor_direction
is the direction of the virtual sensor (“up” or “down”).
You can assign the output of
run_modtran()
to a variable like this:mod_data = run_modtran("my_modtran_file.txt", co2_ppm = 400)
and then you can pass the value ofmod_data
to theplot_modtran()
function, as described below.read_modtran(filename)
allows you to read in a MODTRAN output file (saved to the disk byrun_modtran()
. It returns a list with the same elements asrun_modtran()
.plot_modtran
generates a plot of the radiative spectrum. There are many arguments, and I won’t explain them all here, but the important ones are:modtran_data
is the data that would be returned by therun_modtran()
function. If you want to plotfilename
is the MODTRAN output file with the data to use for the plot.You can also provide data directly to
plot_modtran
instead of reading in a file: Instead of writingplot_modtran("my_modtran_file.txt", ...)
, you could write,plot_modtran(modtran_data = mod_data, ...)
, wheremod_data
is the output ofrun_modtran()
orread_modtran()
.descr
is an optional string to use for the title of the plot. If you don’t specify anything, the function will make a title that indicates the CO2 concentration and the altitude of the virtual sensor.i_out_ref
is a reference value for the outgoing infrared. If you don’t specify it, it’s ignored, but if you specify it, then the plotting function adds an annotation to indicate the difference in outgoing IR between the current run being plotted and the reference value. Typically, you’d run a baseline run of MODTRAN with default parameters and then use the upward IR flux from that run asi_out_ref
when you change the CO2 concentration or other model parameters.delta_t
is the temperature offset for this model run. If you specify it, the plotting function adds an annotation to indicate it.text_size
allows you to adjust the size of the text used for axis labels and the plot title.
Converting temperature units
Some handy functions for converting temperature measurements from one unit of measurement to another are:
ktof(T)
convertsT
from Kelvin to Fahrenheit.ktoc(T)
convertsT
from Kelvin to Celsius.ftok(T)
convertsT
from Fahrenheit to Kelvin.ctok(T)
convertsT
from Celsius to Kelvin.ctof(T)
convertsT
from Celsius to Fahrenheit.ftoc(T)
convertsT
from Fahrenheit to Celsius.
But be aware that if you want to convert the difference between two temperatures, you need to convert the temperatures and then take the difference:
t1_k = 254 # Kelvin temperature
t2_k = 288 # Kelvin temperature
delta_t_k = t2_k - t1_k # Difference in temeprature, in Kelvin
delta_t_k
## [1] 34
t1_f = ktof(t1_k) # Fahrenheit temperatures
t2_f = ktof(t2_k)
t1_f
## [1] -2.47
t2_f
## [1] 58.73
delta_t_f = t2_f - t1_f # Difference in temperature, in Fahrenheit
delta_t_f
## [1] 61.2
# This will give the wrong answer for the
# temperature difference in Fahrenheit!
ktof(delta_t_k)
## [1] -398.47
You see that 58.73 minus -2.47 is not -398.47.
Some variables that I have defined for you are:
sigma_sb
is the Stefan-Boltzmann constant.solar_constant
is the Solar Constant (the intensity of sunlight at the top of the atmosphere, 1350.).
Examples:
modtran_baseline = run_modtran(filename =
file.path(data_dir, "modtran_baseline.txt"))
You could also write this as
run_modtran(filename = file.path(data_dir, "modtran_baseline.txt"))
modtran_baseline = read_modtran(file.path(data_dir, "modtran_baseline.txt"))
Now you can extract the various values from modtran_baseline:
baseline_i_out <- modtran_baseline$i_out
baseline_t_trop <- modtran_baseline$t_trop
The baseline MODTRAN run has \(I_{\text{out}} = 299.\) and \(T_{\text{tropopause}} = 190.\).
plot_modtran(modtran_baseline)
Or you could write
plot_modtran(filename = file.path(data_dir, "modtran_baseline.txt"))
double_co2 = run_modtran(filename = file.path(data_dir, "modtran_double_co2.txt"),
co2_ppm = 800)
plot_modtran(double_co2, i_out_ref = baseline_i_out, delta_t = 0)
mod_file = file.path(data_dir, "modtran_double_co2_warming.txt")
double_co2_warming = run_modtran(filename = mod_file,
co2_ppm = 800, delta_t = 0.76)
plot_modtran(double_co2_warming, i_out_ref = baseline_i_out, delta_t = 0.76)
A few new R functions that we will use in this lab:
Iterating over a series
Sometimes you want to repeat something in R, executing the same commands for
many different values of a variable. We can do this with the for
command:
df = tibble(x = 1:10)
for (i in 1:4) {
p = ggplot(df, aes(x = x, y = x^i)) +
geom_point() + geom_line() +
labs(x = "x", y = str_c("x to the power ", i))
plot(p)
}
This gives us a nice way to run MODTRAN over and over, with many different values for the CO2 concentration and recording the value of Iout for each concentration.
In the loop below, we set all the greenhouse gases to zero and then vary CO2.
We use a trick in R by making an empty tibble before we start the loop and then
for each iteration of the loop, we use bind_rows
to append a row with the
data from that loop iteration.
co2_values = c(0, 200, 400, 600, 800, 1000, 1200)
tbl = tibble()
for (co2 in co2_values) {
filename = str_c("modtran_co2_", co2, ".txt")
mod_data = run_modtran(filename, co2_ppm = co2, ch4_ppm = 0, trop_o3_ppb = 0,
strat_o3_scale = 0, h2o_scale = 0, freon_scale = 0,
atmosphere = "standard", altitude_km = 70)
tbl = bind_rows(tbl, tibble(co2_ppm = co2, i_out = mod_data$i_out))
}
# The digits argument below sets the number of decimal places
# for each column in the table.
kable(tbl, digits = c(co2_ppm = 0, i_out = 1))
This code runs run_modtran
for each value of CO2 in co2_values
and saves the result to a file modtran_0.txt
, modtran_200.txt
, and so
forth. I make the filenames from the values of co2
using the str_c
function,
which I explain below.
Manipulating text in R
R has many functions for manipulating text. When R stores text, it stores it
in character variables (these are also sometimes called “strings” because
text is like a string of characters).
For instance, we might want to make a label or a filename by combining several
variables.
We can use the function str_c
, from the tidyverse
:
print(str_c("infra", "red"))
## [1] "infrared"
print(str_c("infra", "red", sep = "-"))
## [1] "infra-red"
print(str_c(10, "km", sep = " "))
## [1] "10 km"
print(str_c("one", "two", "three", "four", sep = ", "))
## [1] "one, two, three, four"
x = 50
print(str_c(x, "Watts"))
## [1] "50Watts"
print(str_c(x, " Watts"))
## [1] "50 Watts"
print(str_c(x, "Watts", sep = " "))
## [1] "50 Watts"
Notice how str_c
pastes the text together without any spaces between the
parts unless you tell it to use a separator (sep
) between them.
Calculating with leads and lags
Sometimes, when we are using mutate
with a data tibble, we might want to
look at differences between a row and the row before or after it in the
tibble. We can do this with the lead
and lag
functions:
In the example below, the column u
gets the value of the current row of
y
minus the previous row of y
, and the column v
gets the value of the
next row of y
minus the current row of y
. Note that where there isn’t a
previous row, lag
returns NA
(missing value), and similarly for lead
when there isn’t a next row.
tbl = tibble(x = 0:5, y = x^2)
tbl = tbl %>% mutate("lag y" = lag(y), "lead y" = lead(y), u = y - lag(y),
v = lead(y) - y)
kable(tbl)
x | y | lag y | lead y | u | v |
---|---|---|---|---|---|
0 | 0 | NA | 1 | NA | 1 |
1 | 1 | 0 | 4 | 1 | 3 |
2 | 4 | 1 | 9 | 3 | 5 |
3 | 9 | 4 | 16 | 5 | 7 |
4 | 16 | 9 | 25 | 7 | 9 |
5 | 25 | 16 | NA | 9 | NA |
If you want to lead or lag by more than one row, you can just say, lag(y, 5)
to get the value of y
5 rows before the current one.
tbl = tibble(x = 1:10)
tbl = tbl %>% mutate(before = lag(x), after = lead(x),
before.2 = lag(x, 2), after.3 = lead(x, 3))
kable(tbl)
x | before | after | before.2 | after.3 |
---|---|---|---|---|
1 | NA | 2 | NA | 4 |
2 | 1 | 3 | NA | 5 |
3 | 2 | 4 | 1 | 6 |
4 | 3 | 5 | 2 | 7 |
5 | 4 | 6 | 3 | 8 |
6 | 5 | 7 | 4 | 9 |
7 | 6 | 8 | 5 | 10 |
8 | 7 | 9 | 6 | NA |
9 | 8 | 10 | 7 | NA |
10 | 9 | NA | 8 | NA |
Modifying x and y axes in ggplot
It is easy to modify the x or y axis in ggplot
. For instance, if
you want to put specific limits on the axis, or change where the labels
go, you can use scale_x_continuous
or scale_y_continuous
:
tbl = tibble(x = 1:200, y = (x / 100)^5)
ggplot(tbl, aes(x = x, y = y)) + geom_line()
ggplot(tbl, aes(x = x, y = y)) + geom_line() +
scale_x_continuous(limits = c(0,150), breaks = seq(0, 150, 25)) +
scale_y_continuous(limits = c(0,10))
tbl = tibble(x = 1:200, y = 5 - 2 * x + 3 * x^2)
# Note that in R when we are typing numbers, we can express scientific notation
# as 1E6 for 1,000,000 2.67E-3 for 0.00267
ggplot(tbl, aes(x = x, y = y)) + geom_line() +
scale_x_log10(limits = c(1,1000)) +
scale_y_log10(limits = c(1,1E6))
Exercises for Lab #3
You should open the file lab-03-report.Rmd
to do these exercises.
Chapter 4 Exercises
Exercise 4.1: Methane
Methane has a current concentration of 1.7 ppm in the atmosphere and is doubling at a faster rate than CO2.
Would an additional 10 ppm of methane in the atmosphere have a larger or smaller impact on the outgoing IR flux than an additional 10 ppm of CO2 at current concentrations?
Suggestion:
- Run MODTRAN in the default configuration (400 ppm CO2 and 1.7 ppm methane)
- Run MODTRAN with an extra 10 ppm of CO2 and the normal amount of methane.
- Run MODTRAN with the normal amount of CO2 and an extra 10 ppm of methane.
What would you look at from the three runs to figure out whether 10 ppm of methane or 10 ppm of CO2 had the greater effect?
Where in the spectrum does methane absorb? What concentration does it take to begin to saturate the absorption in this band? Explain what you are looking at to judge when the gas is saturated.
Hints:
I recommend setting all the greenhouse gases to zero, and run MODTRAN. Then run MODTRAN for several values of methane, starting at 1 ppm and doubling the concentration until you get to around 128 ppm. You can do this using afor
loop, following the examples from the lab instructions.To set all the greenhouse gases to zero, you would call
run_modtran(co2_ppm = 0, ch4_ppm = 0, trop_o3_ppb = 0, strat_o3_scale = 0, h2o_scale = 0, freon_scale = 0)
The spectrum of methane is complicated so it doesn’t saturate all at once. Use
plot_modtran
to plot the spectrum for each concentration and describe what you see and where you think methane begins to saturate and why.By default,
plot_modtran
gives a plot a title that indicates the CO2 concentration. Here, CO2 doesn’t change and we’re interested in the CH4 concentration, so you can use thedescr
argument toplot_modtran
to give the plots different titles. See the example below.Remember that if you want to make several plots using a
for
loop, you need to assign the result fromplot_modtran
orggplot
to a variable and then use theplot
orprint
function.for (ch4 in ch4_list) { mod_data = run_modtran(co2_ppm = 0, ch4_ppm = ch4, trop_o3_ppb = 0, strat_o3_scale = 0, h2o_scale = 0, freon_scale = 0) p = plot_modtran(mod_data) plot(p) # you could also say print(p) here. }
This will take some time to run because it needs to run MODTRAN for each different value of
ch4
, so you might want to tell R to save the output from the model in a file, and tell R to check whether that file exists and if it does, read from the file instead of running the model again:for (ch4 in ch4_list) { # make a name for the model-output file: "_data/modtran_ch4_0_ppm.txt", # "_data/modtran_ch4_1.7_ppm.txt", etc. mod_file = str_c("_data/modtran_ch4_", ch4, "_ppm.txt") if (! file.exists(mod_file)) { mod_data = run_modtran(filename = mod_file, co2_ppm = 0, ch4_ppm = ch4, trop_o3_ppb = 0, strat_o3_scale = 0, h2o_scale = 0, freon_scale = 0) } else { mod_data = read_modtran(mod_file) } p = plot_modtran(mod_data) plot(p) # you could also say print(p) here. }
But if you do this, then if you change the way you run the model (e.g., change some of the parameters to
run_modtran
, such as the altitude or the atmosphere), you will need to manually delete the files in the_data
directory to make R run the model with the new parameters.Would a doubling of methane have as great an impact on the heat balance as a doubling of CO2?
Suggestion:
- Run MODTRAN in its default configuration (400 ppm CO2 and 1.7 ppm methane)
- Run it again with double the methane concentration.
- Run it again with the default methane (1.7 ppm) but double the CO2 concentration.
- Compare \(I_{\text{out}}\) for the three runs.
What is the “equivalent CO2” of doubling atmospheric methane? That is to say, how many ppm of CO2 would lead to the same change in outgoing IR radiation energy flux as doubling methane? What is the ratio of ppm CO2 change to ppm methane change?
Exercise 4.2: CO2 (Graduate students only)
Is the direct effect of increasing CO2 on the energy output at the top of the atmosphere larger in high latitudes or in the tropics?
Hint: Run MODTRAN with the atmosphere set to
tropical
,midlatitude summer
, andsubarctic summer
, and for each atmosphere, at 400 ppm and 800 ppm CO2. For each atmosphere, calculate the difference between Iout at 400 and 800 ppm CO2 and determine how the effect of doubling CO2 varies as you go from tropical latitudes to subarctic ones.Set pCO2 to an absurdly high value of 10,000 ppm. You will see a spike in the CO2 absorption band. What temperature is this light coming from? Where in the atmosphere do you think this comes from?
Now turn on clouds and run the model again. Explain what you see. Why are night-time temperatures warmer when there are clouds?
Hint: MODTRAN simulates the upward directed, outgoing longwave radiation as seen by a sensor looking down from some height. For the first part of this exercise, start with the sensor at its default altitude of 70 km (you set this with the
altitude_km
argument torun_modtran
), and successively lower it by 10 km at a time until you get to 10 km. What happens to the spike as you lower the sensor? What does this say about what part of the atmosphere is responsible for the spike in the middle of the CO2 absorption at very high values of CO2?For the second part of this exercise, try using “altostratus” clouds.
Exercise 4.3: Water vapor
Our theory of climate presumes that an increase in the temperature at ground level will lead to an increase in the outgoing IR energy flux at the top of the atmosphere.
How much extra outgoing IR would you get by raising the temperature of the ground by 5°C? What effect does the ground temperature have on the shape of the outgoing IR spectrum and why?
HINT: You can raise the temperature of the ground with the
delta_t
artument to MODTRAN.More water can evaporate into warm air than into cool air. Change the model settings to hold the water vapor at constant relative humidity rather than constant vapor pressure (the default), calculate the change in outgoing IR energy flux for a 5°C temperature increase. Is it higher or lower? Does water vapor make the Earth more sensitive to CO2 increases or less sensitive?
Note: By default, the MODTRAM model holds water vapor pressure constant, but you can set it to hold relative humidity constant instead with the option
h2o_fixed = "relative humidity"
, like this:run_modtran(file_name, delta_t = 5, h2o_fixed = "relative humidity")
.Now see this effect in another way.
Starting from the default base case, record the total outgoing IR flux.
Now double CO2. The temperature in the model stays the same (that’s how the model is written), but the outgoing IR flux goes down.
Using constant water vapor pressure, adjust the temperature offset until you get the original IR flux back again. Record the change in temperature.
Now repeat the exercise, but holding the relative humidity fixed instead of the water vapor pressure.
The ratio of the warming when you hold relative humidity fixed to the warming when you hold water vapor pressure fixed is the feedback factor for water vapor. What is it?
Chapter 5 Exercise
Exercise 5.2: Skin Height
Run the MODTRAN model using the “tropical” atmosphere, without clouds, and with the present-day CO2 concentration (400 ppm). Use the ground temperature reported by the model to calculate \(\varepsilon \sigma T_{\text{ground}}^4\), the heat flux emitted by the ground. Assume \(\varepsilon = 1\), and I have already provided the value of the Stefan-Boltzmann constant \(\sigma\), as the R variable
sigma_sb
, which equals 5.670×10-8. (I defined it in the script “utils.R”, which I loaded in the “setup” chunk in the RMarkdown document).Next, look at the outgoing heat flux at the top of the atmosphere (70 km) (Iout) reported by the MODTRAN model. Is it greater or less than the heat flux that you calculated was emitted by the ground?
Use the outgoing heat flux at the top of the atmosphere (Iout) to calculate the skin temperature (use the equation \(I_{\text{out}} = \varepsilon \sigma T_{\text{skin}}^4)\)). What is the skin temperature, and how does it compare to the ground temperature and the temperature at the tropopause, as reported by the MODTRAN model (
t_tropo
)?Assuming an environmental lapse rate of 6K/km, and using the skin temperature that you calculated above, and the ground temperature from the model, what altitude would you expect the skin height to be?
Double the CO2 concentration and run MODTRAN again. Do not adjust the ground temperature. Repeat the calculations from (b) of the skin temperature and the estimated skin height.
What is the new skin temperature? What is the new skin height?
Put the CO2 back to today’s value, but add cirrus clouds, using the “standard cirrus” value for the clouds. Repeat the calculations from (b) of the skin temperature and the skin height.
What is the new skin temperature? What is the new skin height? Did the clouds or the doubled CO2 have a greater effect on the skin height?