Skip to content

Activation Comparison

Compares peak supersaturation \(S_\text{max}\), activated droplet number \(N_\text{act}\), and activated fraction \(f_\text{act}\) predicted by the full parcel model against two widely-used analytical parameterizations:

  • ARG2000 — Abdul-Razzak & Ghan (2000), the standard GCM parameterization.
  • MBN2014 — Morales Betancourt & Nenes (2014), an iterative improvement that accounts for non-equilibrium growth effects.

Both parameterizations are JAX-native, so their outputs are differentiable via jax.grad alongside the parcel model itself.

Script: examples/activation_comparison.py

python examples/activation_comparison.py
python examples/activation_comparison.py --V 2.0 --mu 0.05 --N 500 --kappa 0.54
python examples/activation_comparison.py --plot output/activation_comparison.png

Setup

import pyrcel as pm
from pyrcel.activation import arg2000, mbn2014
import jax.numpy as jnp

aerosol = pm.AerosolSpecies(
    "sulfate",
    pm.Lognorm(mu=0.05, sigma=2.0, N=1000.0),
    kappa=0.54, bins=100,
)

# Ground truth: full ODE integration
model = pm.ParcelModel([aerosol], V=1.0, T0=283.0, S0=-0.02, P0=85000.0)
model.run(300.0, output_dt=1.0, terminate=True)
s = model.summary()

# Analytical parameterizations (single call, no ODE)
mus  = jnp.array([0.05])   # µm
sigs = jnp.array([2.0])
Ns   = jnp.array([1000.0]) # cm⁻³
kaps = jnp.array([0.54])

smax_arg, Nact_arg, frac_arg = arg2000(1.0, 283.0, 85000.0, mus, sigs, Ns, kaps)
smax_mbn, Nact_mbn, frac_mbn = mbn2014(1.0, 283.0, 85000.0, mus, sigs, Ns, kaps)

Console output

Conditions:  V = 1.0 m/s | T = 283.0 K | P = 85000 Pa
Aerosol:     μ = 0.05 µm | σ = 2.0 | N = 1000 cm⁻³ | κ = 0.54

──────────────────────────────────────────────────────────────────
  Method                  Smax (%)    N_act (cm⁻³)           f_act
  ────────────────  ──────────────  ──────────────  ──────────────
  Parcel model              0.2700           636.0          0.6356
  ARG2000                   0.2180           572.0          0.5720
  MBN2014                   0.2502           623.0          0.6230
──────────────────────────────────────────────────────────────────

  Relative error vs parcel model:
    ARG2000:  ΔSmax = -19.2%,  ΔN_act = -10.1%
    MBN2014:  ΔSmax = -7.3%,  ΔN_act = -2.1%

Output figure

Smax, N_act, and f_act comparison across three methods

Each panel compares the same quantity across the three methods. The dashed horizontal line marks the parcel-model reference. At these conditions (V = 1 m/s, μ = 0.05 µm):

  • ARG2000 underestimates \(S_\text{max}\) by ~19% and \(N_\text{act}\) by ~10%, consistent with its known low bias at moderate updraft speeds.
  • MBN2014 agrees more closely with the parcel model (~7% in \(S_\text{max}\), ~2% in \(N_\text{act}\)), reflecting its improved treatment of non-equilibrium droplet growth.

Errors vary with aerosol size, hygroscopicity, and updraft speed — see Sensitivity Sweep for how the relative performance of each method changes across the \((V, \mu)\) parameter space.

Differentiating parameterizations

Because arg2000 and mbn2014 are pure JAX functions, their gradients with respect to any input are available at no extra cost:

import jax

def nact_mbn(V, mu):
    _, Nact, _ = mbn2014(
        V, 283.0, 85000.0,
        jnp.array([mu]), jnp.array([2.0]),
        jnp.array([1000.0]), jnp.array([0.54]),
    )
    return Nact[0]

dNact_dV  = jax.grad(nact_mbn, argnums=0)(1.0, 0.05)
dNact_dmu = jax.grad(nact_mbn, argnums=1)(1.0, 0.05)

These exact analytical gradients are compared against the parcel model's gradients in the Sensitivity Sweep example.