Vertical Modes
Vertical mode decomposition and coupling for multi-layer quasi-geostrophic models.
Coupling Matrix
finitevolx.build_coupling_matrix(H, g_prime)
Build the tridiagonal vertical coupling (stratification) matrix A.
A encodes the buoyancy coupling between layers via layer thicknesses and
reduced gravities. For positive H and g_prime, A is tridiagonal
and diagonally similar to a symmetric positive-definite matrix; it
becomes exactly symmetric when all layer thicknesses are equal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
H
|
Float[Array, 'nl']
|
Layer resting thicknesses [m]. All values must be positive. |
required |
g_prime
|
Float[Array, 'nl']
|
Reduced gravities [m s⁻²]. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, 'nl nl']
|
Tridiagonal coupling matrix A of shape |
Examples:
Single-layer case:
>>> import jax.numpy as jnp
>>> H = jnp.array([1000.0])
>>> g_prime = jnp.array([9.81])
>>> A = build_coupling_matrix(H, g_prime)
>>> A.shape
(1, 1)
Two-layer case with equal thicknesses:
>>> H = jnp.array([500.0, 500.0])
>>> g_prime = jnp.array([0.02, 0.02])
>>> A = build_coupling_matrix(H, g_prime)
>>> A.shape
(2, 2)
Source code in finitevolx/_src/vertical/vertical_modes.py
Mode Decomposition
finitevolx.decompose_vertical_modes(A, f0)
Eigendecompose the coupling matrix A to get Rossby radii and transforms.
Uses jnp.linalg.eigh (Hermitian eigendecomposition) for numerical
stability and JAX-JIT compatibility. A is treated as symmetric
positive-semi-definite, which is exact when all layer thicknesses are equal.
The eigenvectors R are orthonormal, so::
Cl2m = Rᵀ
Cm2l = R
Cl2m @ Cm2l = Rᵀ R = I
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A
|
Float[Array, 'nl nl']
|
Vertical coupling matrix (from :func: |
required |
f0
|
float
|
Reference Coriolis parameter [s⁻¹]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
rossby_radii |
Float[Array, 'nl']
|
Rossby deformation radii [m] for each vertical mode. The barotropic mode (zero eigenvalue) has an infinite radius. |
Cl2m |
Float[Array, 'nl nl']
|
Layer-to-mode transform matrix. |
Cm2l |
Float[Array, 'nl nl']
|
Mode-to-layer transform matrix. |
Examples:
Two-layer decomposition:
>>> import jax.numpy as jnp
>>> H = jnp.array([500.0, 500.0])
>>> g_prime = jnp.array([0.02, 0.02])
>>> A = build_coupling_matrix(H, g_prime)
>>> radii, Cl2m, Cm2l = decompose_vertical_modes(A, f0=1e-4)
>>> radii.shape
(2,)
>>> Cl2m.shape
(2, 2)
Source code in finitevolx/_src/vertical/vertical_modes.py
Layer ↔ Mode Transforms
finitevolx.layer_to_mode(field, Cl2m)
Transform a field from layer space to mode space.
Applies the layer-to-mode transform matrix along the leading (layer) axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
field
|
Float[Array, 'nl *rest']
|
Field in layer space. The first dimension is the layer index; any
trailing dimensions (e.g. |
required |
Cl2m
|
Float[Array, 'nl nl']
|
Layer-to-mode transform matrix (from :func: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, 'nl *rest']
|
Field in mode space, same shape as input. |
Examples:
>>> import jax.numpy as jnp
>>> field = jnp.ones((3,)) # 3-layer 0-D
>>> Cl2m = jnp.eye(3)
>>> layer_to_mode(field, Cl2m)
Array([1., 1., 1.], dtype=float32)
Source code in finitevolx/_src/vertical/vertical_modes.py
finitevolx.mode_to_layer(field, Cm2l)
Transform a field from mode space to layer space.
Applies the mode-to-layer transform matrix along the leading (mode) axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
field
|
Float[Array, 'nl *rest']
|
Field in mode space. The first dimension is the mode index; any trailing dimensions are preserved. |
required |
Cm2l
|
Float[Array, 'nl nl']
|
Mode-to-layer transform matrix (from :func: |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, 'nl *rest']
|
Field in layer space, same shape as input. |
Examples:
>>> import jax.numpy as jnp
>>> field = jnp.ones((3,)) # 3-mode 0-D
>>> Cm2l = jnp.eye(3)
>>> mode_to_layer(field, Cm2l)
Array([1., 1., 1.], dtype=float32)