Atmosphere functions

Functions below are designed to operate on atmosphere object, and for the time being mostly on EarthAtmosphere ones.

Updates and roll-backs

Atmosphere objects, just as EarthAtmosphere, are generally mutated during the course of an inverse retrieval problem. There is no "history" per se that would allow to unambiguously re-create the atmospheric state at some earlier iteration. Due to the flexibility of the toolset, it is always possible to make changes (intentional or not) to the atmospheric state that would be difficult to revert.

The mechanism that is used in RetrievalToolbox relies on user discipline. Let atm be an EarthAtmosphere that has been initialized and adjusted to the user's wishes, and let SV be a RetrievalStateVector that contains state vector elements that imply some modification of the contents of atm.

For some parts of the atmosphere, their state can be easily and directly inferred from a state vector element. As an example we can look at SurfacePressureSVE: the lowest pressure level is simply set to the current value of that state vector element via the atmosphere_element_statevector_update! function. One can think of the surface pressure of the model atmosphere being quite rigidly controlled, it will simply take on whatever value SurfacePressureSVE currently has. This allows us to also recreate the surface pressure that was present at an earlier iteration. We could manipulate the contents of the .iterations field of the SurfacePressureSVE object, i.e. remove entries up to the requested iteration number. When we call atmosphere_element_statevector_update! again, the atmosphere will revert back to that earlier state.

The above holds true for many state vector elements that control the atmospheric state, like the GasVMRProfileSVE which defines the volume mixing ratio profile of a certain gas in that model atmosphere, or SIFRadianceSVE which defines the magnitude of surface-leaving fluorescence radiance emission.

There are notable exceptions, for which this concept does not work - at least not reliably. GasLevelScalingFactorSVE, for example, scales the initial gas profile by some factor. Similarly, TemperatureOffsetSVE adds some value to the initial temperature profile. While it is mathematically straightforward to reconstruct the these profiles from the implicit history of iterations that is found in the .iterations vectors of these state vector elements, it has proven to be not fully reliable in practice.

Instead, RetrievalToolbox expects users to to call a function atmosphere_element_statevector_rollback! towards the end of their forward model implementation, which re-sets particular atmospheric components to their initial state. Therefore, when a new forward model evaluation is performed, the call to atmosphere_element_statevector_update! will modify those components correctly to the desired state as given by the state vector elements.

Warning

Important! There is no mechanism to check if the update and rollback functions have been called in a forward model. It is fully up to users to ensure that those calls are made in the forward model in the appropriate places.

To summarize, users should make a call to atmosphere_element_statevector_update! towards the beginning of their forward model, and then another call to atmosphere_element_statevector_rollback! towards the end.

# My forward model

# [...]
for atm_e in atm.atm_elements
    RE.atmosphere_element_statevector_update!(atm_e, SV)
end

# [...]
# calculate radiances, Jacobians etc.
# [...]

for atm_e in atm.atm_elements
    RE.atmosphere_element_statevector_rollback!(atm_e, SV)
end

# [...]
# forward model end
Tip

Users also must ensure that atmosphere_element_statevector_update! is called after iterations are complete if they want to e.g. calculate some atmospheric quantity corresponding to the final state inferred by the retrieval.

Note that the code snipped shows explicit loops over all atmosphere elements atm_e of some atmosphere atm.

List of atmosphere functions

RetrievalToolbox.JPL_gravityMethod
JPL_gravity(
    latitude::Number,
    altitude::Number;
    earth_equatorial_radius
) -> Any

Calculates local gravity given some latitude and altitude. Note that the altitude can be be a simple number, in which the input is assumed to be in meters. If you supply a Unitful quantity, appropriate unit conversions are done. In either case, this function will return a Unitful quantity that will reduce to acceleration [m s⁻²].

Details

This code was taken from MS3 / the CSU simulator suite, with heritage related to the OCO-1 retrieval algorithm written at JPL. See https://github.com/nasa/RtRetrievalFramework at ./lib/implementation/altitude_hydrostatic.cc.

RetrievalToolbox.atmosphere_element_statevector_update!Method
atmosphere_element_statevector_update!(
    atm_element::AbstractAtmosphereElement,
    sve::AbstractStateVectorElement
) -> Any

Default function to update the atmosphere element atm_element according to the current value of the state vector element sve. This does nothing!

RetrievalToolbox.atmosphere_element_statevector_update!Method
atmosphere_element_statevector_update!(
    atm_elements::Array{T<:AbstractAtmosphereElement, 1},
    SV::AbstractStateVector
)

Function to update all atmosphere elements in the vector atm_elements according to the current value of all state vector elements in the state vector SV.

RetrievalToolbox.calculate_altitude_and_gravity!Method
calculate_altitude_and_gravity!(scene::EarthScene)

Calculates altitude and gravity for an EarthScene, assuming that all other needed quantities have been inserted accordingly, namely: pressure levels, temperatures layers, specific humidity layers and location. Note! Layer-based values are calculated in this function call and overwrite existing values!

RetrievalToolbox.calculate_altitude_and_gravity_levels!Method
calculate_altitude_and_gravity_levels!(
    z_levels::AbstractVector,
    g_levels::AbstractVector,
    p_levels::AbstractVector,
    T_layers::AbstractVector,
    SH_layers::AbstractVector,
    p_surf::Number,
    location::EarthLocation
)

Calculates altitude and gravity levels for Earth-type atmospheres, in-place. For now, this function over-writes altitude_levels and gravity_levels in units of m and m/s^2 respectively!

Details

Given some atmospheric inputs (p, T, q) and the scene latitude and altitude, this function calculates the altitude and gravity profiles (on levels) corresponding to the pressure levels. These outputs should then be used to construct atmosphere objects (EarthAtmosphere).

At this point, p_levels must be in [Pa], T_layers in [K], SH_layers in [1], and the location.altitude in [m]. Alternatively, Unitful arrays with units can be used.

RetrievalToolbox.calculate_gravity_from_z!Method
calculate_gravity_from_z!(atm::EarthAtmosphere; g)

Calculates local gravity based on altitude levels. The optional argument g can be supplied if users want a latitude=dependent surface-level gravity. Otherwise the standard gravity g0 (9.80655 ms⁻²) is used. Note that g must be in compatible units of acceleration.

Details

The gravity $g'(z)$ at altitude $z$ is calculated as

$g'(z) = g \cdot (\frac{R_e}{R_e + z})^2$

where $R_e$ is the (mean) Earth radius and $g$ is the assumed gravity at the surface.

RetrievalToolbox.calculate_layers!Method
calculate_layers!(atm::EarthAtmosphere)

In-place calculation of mid-layer values for all relevant profiles in an EarthAtmosphere object (p, p MET, q, T, z, g).

RetrievalToolbox.calculate_xgasMethod
calculate_xgas(atm::AbstractAtmosphere; gas_name) -> Dict

Calculates the XGAS from an AbstractAtmosphere atm.

The column-averaged dry-air mole fraction is calculated according to O'Dell et al., 10.5194/amt-5-99-2012. Note that the returned quantity comes with the same unit as defined in the GasAbsorber object, which defines the VMR levels of that particular gas.

RetrievalToolbox.create_ACOS_pressure_gridMethod
create_ACOS_pressure_grid(
    psurf::Union{Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}, Unitful.Level{L, S, Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}} where {L, S}} where {T, U}
) -> Vector

Creates the ACOS-type pressure grid on 20 levels

RetrievalToolbox.create_UoL_pressure_gridMethod
create_UoL_pressure_grid(
    p_surf::Union{Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}, Unitful.Level{L, S, Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}} where {L, S}} where {T, U},
    p_tropo::Union{Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}, Unitful.Level{L, S, Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}} where {L, S}} where {T, U};
    N_total
) -> Vector

Creates the 'classic' University of Leicester-type pressure grid, based on the supplied surface pressure p_surf and the tropopause pressure p_tropo.

Details

A pressure grid is generated with fixed 5 stratospheric levels. The sixth level is halfway between tropopause pressure and level 5, and the seventh level is the tropopause pressure itself. Finally, the remaining levels are evenly spaced between the tropopause and the surface pressure. The total number of pressure levels must be greater than 8 (default: 20). If the tropopause pressure is larger than 8000 Pa (i.e. higher in the atmosphere), levels 6 and 7 are then set to predefined values and the tropopause is then considered to be level 7.

RetrievalToolbox.create_empty_EarthAtmosphereMethod
create_empty_EarthAtmosphere(
    Nlev::Integer,
    Nlev_met::Integer,
    T::Type{<:Real};
    pressure_unit,
    met_pressure_unit,
    temperature_unit,
    specific_humidity_unit,
    altitude_unit,
    gravity_unit
) -> EarthAtmosphere

Creates an empty EarthAtmosphere object with the specified number of retrieval grid levels, meteorological grid levels, array type T as well as units for the profiles. This function takes optional arguments to define the units for the various profiles.

RetrievalToolbox.create_example_atmosphereMethod
create_example_atmosphere(
    name::String,
    Nlev::Integer;
    T,
    surface_pressure,
    altitude,
    is_example
) -> EarthAtmosphere{Float64}

Creates an EarthAtmosphere object based on some representative atmospheres that were extracted from NASA GMAO's MERRA2 reanalysis and Sourish Basu's CO2/CH4. Must provide the name of the example atmosphere name as well as the intended number of pressure levels for the retrieval grid, Nlev, to be filled out be the user later.

Optional arguments are surface_pressure or altitude (must choose one or none, never both) to adjust the model atmosphere accordingly.

RetrievalToolbox.create_example_gas_profileMethod
create_example_gas_profile(
    name::String,
    gas_name::String,
    spec::AbstractSpectroscopy,
    plevels::Vector{<:Union{Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}, Unitful.Level{L, S, Unitful.Quantity{T, 𝐌 𝐋^-1 𝐓^-2, U}} where {L, S}} where {T, U}};
    is_example
) -> GasAbsorber

Creates a gas profile from an example atmosphere, and attaches it to a supplied spectroscopy object spec. Pressure levels must also be given, which have to match the retrieval pressure levels.

RetrievalToolbox.create_level_from_midlayerMethod
create_level_from_midlayer(q) -> Any

Creates a level-based profile from one defined on middle-of-the-layer. Assumes that the mid-layer value is well-approximated by half the value of the layer-boundary values.

RetrievalToolbox.create_pressure_weightsMethod
create_pressure_weights(
    atm::AbstractAtmosphere;
    N_sub
) -> Any

Calculates the pressure weights according to O'Dell et al. in 10.5194/amt-5-99-2012. Between layer boundaries, a sub-layer numerical integration is used to calculate the $(1-q) / (g * M_\mathrm{dry})$ term, where N_sub determines the number of sub-layers. Note that this assumes that the gas concentrations vary linearly with pressure, as implemented in the function calculate_gas_optical_depth_profiles.

RetrievalToolbox.get_gas_from_nameMethod
get_gas_from_name(
    atm::EarthAtmosphere,
    name::String
) -> Union{Nothing, AbstractAtmosphereElement}

Given an atmosphere object, this function returns a reference to the gas object whose name is the same as some string name.

RetrievalToolbox.update_specific_humidity_from_H2O!Method
update_specific_humidity_from_H2O!(
    atm::EarthAtmosphere
) -> Bool

Updates the specific humidity profile of the atmosphere atm, if an H2O profile is available as an atmospheric element. Does not update gravity and altitude profiles!