Go to notebook file


[1]:
%reload_ext eradiate.notebook.tutorials

Last updated: 2022-10-05 13:34 (eradiate v0.22.4.post102+g84ef86b.d20221005)

Molecular atmosphere basics#

Overview

In this tutorial, we introduce Eradiate’s molecular atmosphere simulation features.

Prerequisites

What you will learn

  • How to configure a standard 1D atmospheric profile.

  • How to rescale the atmospheric composition of standard profiles to fit more current data.


Importing modules#

We start by importing the eradiate, numpy and matplotlib.pyplot modules. Additionally, we load the Eradiate IPython extension for a smoother notebook experience.

[2]:
%load_ext eradiate
import eradiate
import numpy as np
import matplotlib.pyplot as plt

We also import the MolecularAtmosphere class and alias the unit registry for convenience:

[3]:
from eradiate.scenes.atmosphere import MolecularAtmosphere
from eradiate import unit_registry as ureg

We will perform simulations in narrow bands using Eradiate’s correlated-k distribution mode (ckd). There is indeed little point performing monochromatic simulations, at least in this tutorial: running such simulations to compute the signal recorded for a given spectral band is very costly, and the CKD method brings in a significant speed-up.

[4]:
eradiate.set_mode("ckd")

Creating a standard molecular atmosphere#

The most obvious way to configure a molecular atmospheric profile would be to call the MolecularAtmosphere constructor; however, proper initialisation of standard profiles is supposed to be done using specialised class method constructors. In CKD mode, the AFGL 1986 reference atmospheres [ACC+86] are supported and created using the MolecularAtmosphere.afgl_1986() class method:

[5]:
us_standard_atmosphere = MolecularAtmosphere.afgl_1986()

We just instantiated an molecular atmosphere object with default parameters. It notably uses the “U.S. Standard” reference atmospheric profile, default molecular density values and discretises the atmosphere vertically in 120 1 km-thick layers:

[6]:
us_standard_atmosphere
MolecularAtmosphere(
    id='atmosphere',
    geometry=None,
    scale=None,
    _thermoprops=<xarray.Dataset>
Dimensions:  (z_level: 121, z_layer: 120, species: 7)
Coordinates:
  * z_level  (z_level) float64 0.0 1.0 2.0 3.0 4.0 ... 117.0 118.0 119.0 120.0
  * z_layer  (z_layer) float64 0.5 1.5 2.5 3.5 4.5 ... 116.5 117.5 118.5 119.5
  * species  (species) object 'H2O' 'O3' 'N2O' 'CO' 'CH4' 'CO2' 'O2'
Data variables:
    p        (z_layer) float64 9.559e+04 8.469e+04 ... 0.002981 0.002687
    t        (z_layer) float64 284.9 278.4 271.9 265.4 ... 330.0 342.0 354.0
    n        (z_layer) float64 2.43e+25 2.203e+25 ... 6.486e+17 5.571e+17
    mr       (species, z_layer) float64 0.00691 0.00535 ... 0.07895 0.07465
Attributes:
    convention:  CF-1.8
    title:       AFGL (1986) U.S. Standard atmosphere thermophysical properties
    history:     2021-05-19 17:37:17 - data creation - shicho.afgl86.make_dat...
    source:      Atmospheric model (U.S. Standard Atmosphere) adapted from sa...
    references:  Anderson, G.P. and Chetwynd J.H. and Clough S.A. and Shettle...
    comment:     raw data was linearly interpolated on a regular layer altitu...
    identifier:  afgl_1986-us_standard,
    phase=RayleighPhaseFunction(id='phase_atmosphere'),
    has_absorption=True,
    has_scattering=True,
    absorption_data_sets=None
)

Eradiate supports the 6 AFGL reference atmospheres (see the MolecularAtmosphere.afgl_1986() API documentation for the complete list). We can visualise the pressure and temperature profiles:

[7]:
def show_profile(*atmospheres, labels=None):
    from matplotlib.ticker import ScalarFormatter

    if labels is None:
        label_iter = iter([None for _ in atmospheres])
    else:
        label_iter = iter(labels)

    fig, axs = plt.subplots(1, 2, sharey=True)

    for atmosphere in atmospheres:
        temperature = atmosphere.radprops_profile.thermoprops.t
        pressure = atmosphere.radprops_profile.thermoprops.p

        with plt.rc_context({"lines.linestyle": ":", "lines.marker": "."}):
            temperature.plot(y="z_layer", ax=axs[0])
            pressure.plot(y="z_layer", ax=axs[1], label=next(label_iter))

    formatter = ScalarFormatter(useMathText=True)
    formatter.set_powerlimits((-3,2))
    axs[1].xaxis.set_major_formatter(formatter)
    axs[1].set_ylabel("")

    if labels is not None:
        fig.legend(
        bbox_to_anchor=(1.0, 0.5),
        loc="center left",
        borderaxespad=0.0,
    )

    plt.tight_layout()
    plt.show()
    plt.close()

show_profile(us_standard_atmosphere)
../../_images/tutorials_getting_started_molecular_atmosphere_15_0.png

The reference atmosphere is controlled by the model parameter. For instance, the Midlatitude Summer reference atmosphere can be obtained with the midlatitude_summer value. Let’s add it to our plot:

[8]:
midlatitude_summer_atmosphere = MolecularAtmosphere.afgl_1986(
    model="midlatitude_summer"
)
show_profile(
    us_standard_atmosphere,
    midlatitude_summer_atmosphere,
    labels=["U.S. Standard", "Midlatitude Summer"],
)
../../_images/tutorials_getting_started_molecular_atmosphere_17_0.png

Changing the altitude grid#

The altitude grid can be specified manually using the levels parameter. To change the number of levels to 26 (25 layers) and have the profile extend between 0 and 100 km, we simply have to write:

[9]:
us_standard_atmosphere_custom = MolecularAtmosphere.afgl_1986(
    model="us_standard",
    levels=np.linspace(0, 100, 26) * ureg.km,
)
[10]:
show_profile(us_standard_atmosphere_custom)
../../_images/tutorials_getting_started_molecular_atmosphere_20_0.png

tutorials/getting_started/molecular_atmosphere.ipynb## Rescaling species concentration values

Arguably, reference atmospheric profiles are not always appropriate. In particular, the chemical composition of the atmosphere significantly varies as a function of time and location. Eradiate can vary reference profiles by rescaling species concentrations to account for the effects of a changing atmospheric composition. This is done using the concentrations parameter. The following example varies the U.S. Standard atmosphere by setting:

  • the column mass density of water vapour to 15 kg / m²,

  • the volume mixing ratio of CO₂ at sea level to 400 ppm,

  • the column number density of O₃ to 350 Dobson units.

[11]:
us_standard_atmosphere_custom = MolecularAtmosphere.afgl_1986(
    model="us_standard",
    concentrations={
        "H2O": 15.0 * ureg.kg / ureg.m ** 2,  # column mass density
        "CO2": 400e-6 * ureg.dimensionless,  # volume mixing fraction at sea level
        "O3": 350.0 * ureg.dobson_units,  # column number density
    },
)

Disabling absorption or scattering#

The absorption or scattering coefficient can be forced to 0 using the has_absorption and has_scattering switches. The following atmosphere definition has no absorption, only Rayleigh scattering:

[12]:
rayleigh_atmosphere = MolecularAtmosphere.afgl_1986(
    has_absorption=False, has_scattering=True
)

What about the monochromatic mode?#

In mono mode, the AFGL 1986 atmospheric profiles are not supported. We provide instead the simpler U.S. Standard Atmosphere (1976) [NNU76], which lacks many species contributing to radiative processes. This profile is accessed using the MolecularAtmosphere.ussa_1976() class method:

[13]:
us76_atmosphere = MolecularAtmosphere.ussa_1976()

Profile customisation options are similar to those of the AFGL 1986 profiles.


Final words#

The various instantiation and customisation options we explored in this tutorial can be used in all the experiments supporting 1D atmospheric profiles.

Further reading#