CloudToppedMixedLayerModel
ConceptualClimateModels.CloudToppedMixedLayerModel — Module
CloudToppedMixedLayerModelSubmodule providing processes about cloud topped mixed layer models (MLMs). This combines existing equations on MLM by (Stevens, 2006) and (Bretherton and Wyant, 1997), with surface energy balance and dynamic cloud equations. It is developed as part of the research article (Datseris, 2026). If you use this submodule, please cite the paper.
The organization is as follows:
- All important variables and parameters (participate in many processes) are defined in the module file and as module-level scoped variables (global variables). Click the "source" of this docstring to access the module file.
- All processes (physical equations) are defined in their respective files such as
free_troposhere.jl, etc. Docstrings of important processes are expanded in the docs here. You will notice that all functions that return processes (equations) utilize these global variables and global parameters. Many of these functions will also define local variables and parameters. All noteworthy processes have docstrings that are expanded in the submodule online documentation. However, the majority of docstrings do not actually list the equations themselves. Simply click the "source code" button on the bottom right of each docstring to go to the source code. Because this package is written in Julia, and because it uses symbolic expressions throughout, reading the source code is truly as straight forward as reading Latex-rendered equations. - The
default.jlfile defines default processes for many global variables. These are also expanded in the docs.
Throughout the submodule time is in units of days, specific humidity is in units of g/kg, liquid water static energy is in units of K (i.e., normalized by cₚ), height in meters, temperature in K, and all energy quantities are in W/m².
To learn how to use this submodule visit first the general tutorial of ConceptualClimateModels.jl and then the dedicated example on a cloudy mixed layer model. The module purposefully does not export any names, so the recommended way to use it is by an alias: import ConceptualClimateModels.CloudToppedMixedLayerModel as CTMLM.
Mixed layer
ConceptualClimateModels.CloudToppedMixedLayerModel.mlm_dynamic — Function
mlm_dynamic()Provide equations 1-3 in (Datseris, 2026) (or, 31-33 in (Stevens, 2006)) defining the bulk boundary layer dynamics. An additional auxilary velocity $w_m$ is added in the equation for $z_b$ and two auxilary export terms $q_x, s_x$ are added to the equations for $q_b, s_b$. All these auxilarity terms are 0 by default (otherwise, assign a process to them).
ConceptualClimateModels.CloudToppedMixedLayerModel.bbl_stevens2006_steadystate — Function
bbl_stevens2006_steadystate(fixed; z_b, q_b, s_b, RCT)Return the equations 35-38 in (Stevens, 2006) describing the analytically solved steady state of the MLM. These equations could be coupled to other parts of module but we have a problem of circular dependency for the steady state of $z_b$. If we attempt to couple them with the dynamic equations for $C$, then the following:
z_b ~ h⃰ * (e_e*σ_38)/(1 + σ_38 - e_e),
σ_38 ~ V*Δs*cₚ/(ΔF_s/ρ₀),yields a circular dependency: z_b depends on σ_38 which depends on ΔF_s which depends on T_t which depends on z_b. To resolve this a fixed option is given, which can be any of: ΔF_s, z_b, w_s, T_t. This quantity is set fixed and becomes a parameter so that the equation for z_b is closed.
ConceptualClimateModels.CloudToppedMixedLayerModel.temperature_exact — Function
temperature_exact(z, s, q)Use root-finding to find the temperature at height z given the liquid water static energy and total specific humidity, as described by (Stevens, 2006). This is the default equation used for T_t ~ temperature_exact(z_b, s_b, q_b).
ConceptualClimateModels.CloudToppedMixedLayerModel.entrainment_velocity — Function
entrainment_velocity(version = :Stevens2006; use_augmentation = true)Return an equation for the entrainment velocity $w_e$. Versions are :Stevens2006, :Gesso2014, :LL96. Keyword use_augmentation adds the decoupling-based augmentation described in (Datseris, 2026). Keyword use_shear adds the shear augmentation from (Zhang et al., 2009).
ConceptualClimateModels.CloudToppedMixedLayerModel.q_liquid — Function
q_liquid(T, q, z)liquid specific humidity given temperature total water specific humidity and height. 0.0 if below saturation.
ConceptualClimateModels.CloudToppedMixedLayerModel.q_saturation — Function
q_saturation(T, z)Saturation specific humidity given temperature and height. Height is transformed to pressure via hydrostatic approximation.
ConceptualClimateModels.CloudToppedMixedLayerModel.pressure — Function
pressure(z, T)Use hydrostatic balance and ideal gas law to get pressure at height z given temperature at height z. The equation is often called the "Hypsometric equation" with the factor (RdT/g) called the scale height. Note that normally using Rd requires usage of Tv (virtual temperature), defined as Tv = T(1 + 0.608*q) with q the specific humidity of water vapor. In the codebase we practically always approximate Tv by T.
ConceptualClimateModels.CloudToppedMixedLayerModel.sst_dynamic — Function
Return τSST * d(SST)/dt = ASW - Lnet - LHF - SHF + SST_X .
Clouds and decoupling
ConceptualClimateModels.CloudToppedMixedLayerModel.cf_dynamic — Function
cf_dynamic(; thinness_limiter = false)Provide the equation $\tau_C dC/dt = C_\infty - C$ as well as as many more equations necessary to define $C_\infty$, in particular for $C_\Lambda$ and/or $C_\kappa$. The function uses the curve fitted to data in (Datseris, 2026).
ConceptualClimateModels.CloudToppedMixedLayerModel.cloud_emission_temperature — Function
cloud_emission_temperature(version = :mean)Return a process for $T_C$. Versions are :top, :base, :mean.
ConceptualClimateModels.CloudToppedMixedLayerModel.cloud_emissivity — Function
cloud_emissivity(version = 1.0; fraction = true)Provide an equation for the effective emissivity ε_C of the cloud layer. Options for version:
:clt: inspired by (Randall and Suarez, 1984), emissivity scales with the thickness of the cloud layer.:lwp: Expression given by (Stephens, 1978) where emissivity is an exponential of LWP.<: Number: emissivity is just the provided number or symbolic expression.
If fraction = true the emissivity is further multiplied by the cloud fraction.
ConceptualClimateModels.CloudToppedMixedLayerModel.cloud_albedo — Function
cloud_albedo(version = 0.38; fraction = true)Provide a process for α_C, the cloud albedo. If fraction == true, the expression is further multiplied by the cloud fraction C.
When version == :lwp we use an approach inspired by (Datseris and Stevens, 2021), using the expression from (Lacis and Hansen, 1974)
\[\alpha_C = \alpha_C^{max} \frac{\tau_C}{\tau_C + 1/(\sqrt{3}(1-g_C))}\]
where $\tau_C$ is the cloud optical depth (not the cloud fraction relaxation timescale) and $g_C$ the asymmetry factor for the cloud particle phase function. The optical depth is estimated as a function of the Liquid Water Path, fitted from Fig. 1 of (Stephens, 1978) as
\[\tau_C = \frac{x^{1.7}}{10 + x}\]
with $x$ the LWP in g/m². The expression fits very accurately for LWP up to 10³.
ConceptualClimateModels.CloudToppedMixedLayerModel.cloud_base_height — Function
cloud_base_height(version = :exact, z_cb = z_lcl)Provide an equation for the cloud base height captured by variable z_cb.
:exact: exact estimation by figuring out whenq_liquidfirst becomes positive. Computationally costly as it requires interpolations.:Bolton1980: Well known approximate expression by Bolton, 1980.
Because so far all versions calculate the lifting condensation level, z_cb defaults to z_lcl. (and the default process for z_cb is for it to be z_lcl).
ConceptualClimateModels.CloudToppedMixedLayerModel.liquid_water_path — Function
liquid_water_path()Provide a process for the liquid water path LWP being proportional to CLT^2 by using the assumption that liquid water specific humidity increases linearly with height within the cloud layer.
ConceptualClimateModels.CloudToppedMixedLayerModel.decoupling_variable — Function
decoupling_variable(version = :Bretherton1997)Provide an equation for $\Lambda$, the decoupling variable.
ConceptualClimateModels.CloudToppedMixedLayerModel.decoupling_ratios — Function
decoupling_ratios()Return equations for $\lambda_q, \lambda_s$ as in (Datseris, 2026).
Radiation
ConceptualClimateModels.CloudToppedMixedLayerModel.cloud_shortwave_warming — Function
cloud_shortwave_warming([version]; cloud_fraction = true)Provide an equation for CRCsw (same as CTRCsw) which by default is 0.04*C*S. Otherwise version can be a Number specifying the RHS.
ConceptualClimateModels.CloudToppedMixedLayerModel.cloud_longwave_cooling — Function
cloud_longwave_cooling(cloud_fraction = false)Provide processes for CTRClw, CRClw based on the three-layer radiation balance. If cloud_fraction == false, the RHS are further scaled by C. By default this is not done because typically ε_C is scaled by C.
ConceptualClimateModels.CloudToppedMixedLayerModel.mlm_radiative_cooling — Function
mlm_radiative_cooling(version = :three_layer)Provide an equation for $\Delta F_s$, the radiative cooling of the boundary layer (assumming $\Delta F_q = 0$). Versions are: :three_layer, :ctrc, :Gesso2014 as in (Datseris, 2026).
ConceptualClimateModels.CloudToppedMixedLayerModel.downwards_longwave_radiation — Function
downwards_longwave_radiation([version])Provide equation for $L_d, L_{net}$, the incoming longwave radiation or the net longwave radiative cooling of the surface. See the source code for possible versions.
ConceptualClimateModels.CloudToppedMixedLayerModel.albedo — Function
Return an equation for α the total albedo perceived by the surface.
ConceptualClimateModels.CloudToppedMixedLayerModel.matsunobu_emissivity — Function
matsunobu_emissivity(RH, T, H = 0)Return emissivity at given relative humidity and temperature as defined by (Matsunobu and Coimbra, 2024).
Free troposphere
ConceptualClimateModels.CloudToppedMixedLayerModel.free_troposphere_emission_temperature — Function
free_troposphere_emission_temperature(γ = 1.0; add_co2 = true)Return an equation for $T_{FTR}$. γ is as in (Datseris, 2026). add_co2 will add an additional warming term ECS_CO2*log2(CO2/400). Introduces two extra parameters, T_FTR_0, T₊_0.
ConceptualClimateModels.CloudToppedMixedLayerModel.mlm_s₊ — Function
mlm_s₊(
version = :difference;
cloud_effect = false,
CO2_effect = false,
)Provide equation for $s_+$ depending on version with options:
:difference: the temperature difference across inversion is a fixed parameter.:temperature: the temperature after the inversion is a fixed parameter.:static_energy: the moist static energy after the inversion is a fixed parameter.:lapse_rate: the temperature after the inversion is fixed and given by a prescribed lapse rate, $T_+ = T_{+,ref} + \Gamma_T (z_b - 1000)$ as in (Salazar and Tziperman, 2023) which introduces two additional parameters:Γ_T = 6.5e-3, T₊_ref = 290.0
Besides these, we can also specify whether CO2 increase also increases temperature difference, and whether decreasing $C$ decreases temperature difference due to cloud thinning as in (Singer and Schneider, apr 2023).
ConceptualClimateModels.CloudToppedMixedLayerModel.mlm_q₊ — Function
mlm_q₊(version = :relative)Provide equation for $q_+$. If version = :relative then make free tropospheric relative humidity RH₊ a free parameter. Else if version = :constant then make q₊ itself a parameter. Else if version = :lapse_rate prescribe $q_+ = q_{+, ref} - \Gamma_q(z_b - 1000)$ which introduces parameters Γ_q = 1.5e-3, q₊_ref = 2.0, inspired by (Park et al., 2004).
Default processes
using ConceptualClimateModels
import ConceptualClimateModels.CloudToppedMixedLayerModel as CTMLM
default_processes_eqs(CTMLM)46-element Vector{Equation}:
λ_q(t) ~ 0
T_FTR(t) ~ T₊(t)
T_lcl(t) ~ -0.009760956175298806CLT(t) + s_b(t)
λ_s(t) ~ 0
ε_b(t) ~ clamp(0.62 + 1.642NaNMath.sqrt(0.006002554529377088RH_b(t)*exp((17.625(-273.15 + T_b(t))) / (-30.11 + T_b(t)))), 0, 1)
L_FTR(t) ~ 5.670374419e-8(T_FTR(t)^4)*ε_FTR(t)
α(t) ~ 1 - (1 - α_C(t))*(1 - α_a)*(1 - α_s)
Lnet(t) ~ -Ld(t) + L₀(t)
Δ₀s(t) ~ s_b(t) - s₀(t)
CLT(t) ~ max(-z_cb(t) + z_ct(t), 0)
⋮
z_cb(t) ~ z_lcl(t)
LHF(t) ~ -2530.0V(t)*Δ₀q(t)*ρ₀(t)
V(t) ~ U*d_c
s₀(t) ~ SST(t)
ASW(t) ~ -CRCsw(t) + S(t)*(1 - α(t))
w_m(t) ~ 0
L_c(t) ~ 5.670374419e-8(T_C(t)^4)*ε_C(t)
SHF(t) ~ -1004.0V(t)*Δ₀s(t)*ρ₀(t)
w_D(t) ~ -D*z_b(t)