Met ensemble¶
One footprint per meteorological ensemble member (ensemble_footprints, on GriddedWinds or uniform winds), and the Gaussian inversion that marginalises over them (ensemble_inversion): the mean footprint, with the members' spread at the prior mean added to the observation covariance as a transport error (transport_covariance). Needs the assim extra for the inversion. Tier II.
met_ensemble
¶
Met-ensemble footprints and inversion (implementation in plumax.lagrangian._src.met_ensemble).
ensemble_footprints
¶
ensemble_footprints(winds: Sequence[GriddedWind | Callable[[Array], Array]], receptors: Float[Array, 'obs 3'], turbulence: TurbulenceModel, domain_x: tuple[float, float, int], domain_y: tuple[float, float, int], *, n_particles: int = 5000, t_back: float = 600.0, dt: float = 1.0, pbl_height: float = 1000.0, pbl_fraction: float = 0.5, air_density: float = 1.2, receptor_time: float = 0.0, seed: int = 0) -> Float[Array, 'member obs cell']
Footprint matrix F_e of every ensemble member.
F_e[i, s] = compute_footprint(receptor i, wind e)[s], cells flattened
row-major over (x, y).
Every member reuses the same particle draws for a receptor (common random
numbers: receptor i uses seed seed + i in every member). The spread
between members is then the effect of the winds alone; independent draws
would add particle-sampling noise that :func:ensemble_inversion would count
as transport error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
winds
|
Sequence[GriddedWind | Callable[[Array], Array]]
|
One mean wind per member: a
:class: |
required |
receptors
|
Float[Array, 'obs 3']
|
Receptor positions (x, y, z) [m]. |
required |
turbulence
|
TurbulenceModel
|
Turbulence model, shared by the members. |
required |
domain_x
|
tuple[float, float, int]
|
|
required |
domain_y
|
tuple[float, float, int]
|
|
required |
n_particles
|
int
|
Particles per receptor and member. |
5000
|
t_back
|
float
|
Backward integration time [s]. |
600.0
|
dt
|
float
|
Time step [s]. |
1.0
|
pbl_height
|
float
|
Boundary-layer height [m]. |
1000.0
|
pbl_fraction
|
float
|
Fraction of the PBL that sees the surface flux. |
0.5
|
air_density
|
float
|
Air density [kg m⁻³]. |
1.2
|
receptor_time
|
float
|
Observation time [s] on the winds' clock. |
0.0
|
seed
|
int
|
Base PRNG seed. |
0
|
Returns:
| Type | Description |
|---|---|
Float[Array, 'member obs cell']
|
The member footprints, units s m² kg⁻¹ (see |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in src/plumax/lagrangian/_src/met_ensemble.py
ensemble_inversion
¶
ensemble_inversion(footprints: Float[Array, 'member obs cell'], observation: Float[Array, ' obs'], *, prior_mean: Float[Array, ' cell'], prior_cov: Float[Array, 'cell cell'], obs_variance: Float[Array, ' obs']) -> GaussianPosterior
Gaussian inversion that marginalises the footprint over a met ensemble.
q = q_a + B F̄ᵀ (F̄ B F̄ᵀ + R + R_transport)⁻¹ (y − F̄ q_a), P = B − B F̄ᵀ (F̄ B F̄ᵀ + R + R_transport)⁻¹ F̄ B,
with F̄ and R_transport from :func:transport_covariance. One member gives
:func:~plumax.lagrangian.linear_gaussian_inversion on its footprint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
footprints
|
Float[Array, 'member obs cell']
|
Member footprints F_e (e.g. :func: |
required |
observation
|
Float[Array, ' obs']
|
Observed values y. |
required |
prior_mean
|
Float[Array, ' cell']
|
Prior mean q_a. |
required |
prior_cov
|
Float[Array, 'cell cell']
|
Prior covariance B. |
required |
obs_variance
|
Float[Array, ' obs']
|
Diagonal of the retrieval + representation covariance R. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
The |
GaussianPosterior
|
class: |
Raises:
| Type | Description |
|---|---|
ImportError
|
Without the |
Source code in src/plumax/lagrangian/_src/met_ensemble.py
transport_covariance
¶
transport_covariance(footprints: Float[Array, 'member obs cell'], prior_mean: Float[Array, ' cell']) -> tuple[Float[Array, 'obs cell'], Float[Array, 'obs obs']]
Mean footprint F̄ and linearised transport-error covariance at q_a.
R_transport = Σ_e d_e d_eᵀ / (E − 1), d_e = (F_e − F̄) q_a,
computed by gaussx.ensemble_covariance(..., bessel=True) on F_e q_a,
and zero for a single member.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
footprints
|
Float[Array, 'member obs cell']
|
Member footprints F_e. |
required |
prior_mean
|
Float[Array, ' cell']
|
Prior mean q_a, the linearisation point. |
required |
Returns:
| Type | Description |
|---|---|
tuple[Float[Array, 'obs cell'], Float[Array, 'obs obs']]
|
|
Examples:
Two members that disagree on one receptor:
>>> import jax.numpy as jnp
>>> footprints = jnp.array([[[1.0, 0.0], [0.0, 1.0]], [[3.0, 0.0], [0.0, 1.0]]])
>>> mean_footprint, covariance = transport_covariance(
... footprints, jnp.array([1.0, 1.0])
... )
>>> mean_footprint.tolist(), covariance.tolist()
([[2.0, 0.0], [0.0, 1.0]], [[2.0, 0.0], [0.0, 0.0]])
Identical members carry no transport error:
>>> same = jnp.stack([footprints[0], footprints[0]])
>>> bool((transport_covariance(same, jnp.ones(2))[1] == 0.0).all())
True