Go to notebook file


[1]:
%reload_ext eradiate.notebook.tutorials

Last updated: 2023-06-22 19:48 (eradiate v0.23.2rc2.post1.dev5+gedede817.d20230622)

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 [Anderson et al., 1986] 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
[6]:
MolecularAtmosphere(id='atmosphere', geometry=PlaneParallelGeometry(toa_altitude=120.0 km, ground_altitude=0.0 km, zgrid=ZGrid(levels=[0.0 100.0 200.0 ... 119800.0 119900.0 120000.0] m, _layers=[50.0 150.0 250.0 ... 119750.0 119850.0 119950.0] m, _layer_height=100.0 m, _total_height=120000.0 m), width=1000000.0 km), scale=None, _thermoprops=<xarray.Dataset | source='/Users/leroyv/Documents/src/rayference/rtm/eradiate/resources/data/thermoprops/afgl_1986-us_standard.nc'>, _phase=RayleighPhaseFunction(id='phase_atmosphere'), has_absorption=True, has_scattering=True, absorption_dataset=<xarray.Dataset | source='/Users/leroyv/Documents/src/rayference/rtm/eradiate/resources/downloads/unstable/ckd/absorption/10nm/afgl_1986-us_standard-10nm-v3.nc'>)

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) [NASA et al., 1976], 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#