Source code for pygotm.turbulence.kbalgebraic

# ruff: noqa: E501
"""
Algebraic closure for buoyancy variance :math:`k_b`.

Implements GOTM Section 4.7.30 (kbalgebraic.F90) — computes the buoyancy
variance :math:`k_b = \\langle b'^2 \\rangle / 2` under the algebraic
equilibrium assumption.

The equilibrium condition :math:`P_b = \\varepsilon_b` (Eq. 171) is assumed,
where :math:`P_b` is the buoyancy-variance production.  Using the definition
of the time-scale ratio :math:`r = c_b` (Eq. 66), this gives (Eq. 172):

.. math::

   k_b = \\frac{k_{b\\varepsilon}}{k\\varepsilon} P_b
       = r \\frac{k}{\\varepsilon} P_b
       = c_b \\frac{k}{\\varepsilon} P_b \\point

In the code, the coefficient :math:`c_b` is passed as ``ctt`` (the scalar
turbulence time-scale ratio).

The result is clipped to ``kb_min`` to prevent negative values.

Author (original Fortran): Lars Umlauf.
"""

import numba
import numpy as np

from pygotm.arrays import ColumnWorkspace, make_column_array

__all__ = [
    "KBAlgebraicWorkspace",
    "step_kbalgebraic",
    "step_kbalgebraic_single",
]


[docs] class KBAlgebraicWorkspace(ColumnWorkspace): """Workspace arrays for the algebraic buoyancy-variance closure.""" tke: np.ndarray eps: np.ndarray kb: np.ndarray Pb: np.ndarray def __init__(self, nlev: int, *, n_cols: int | None = None) -> None: super().__init__(nlev, n_cols=n_cols) self.tke = make_column_array(nlev, n_cols=n_cols) self.eps = make_column_array(nlev, n_cols=n_cols) self.kb = make_column_array(nlev, n_cols=n_cols) self.Pb = make_column_array(nlev, n_cols=n_cols)
@numba.njit(cache=True) def _step_kbalgebraic( nlev: int, ctt: float, kb_min: float, tke: np.ndarray, eps: np.ndarray, kb: np.ndarray, Pb: np.ndarray, ) -> None: r"""Advance the algebraic buoyancy-variance closure (single column).""" for i in range(nlev + 1): kb[i] = ctt * tke[i] / eps[i] * Pb[i] if kb[i] < kb_min: kb[i] = kb_min
[docs] @numba.njit(parallel=True, cache=True) def step_kbalgebraic( batch_size: int, nlev: int, ctt: float, kb_min: float, tke: np.ndarray, eps: np.ndarray, kb: np.ndarray, Pb: np.ndarray, ) -> None: r"""Advance the algebraic buoyancy-variance closure (batch).""" for b in numba.prange(batch_size): _step_kbalgebraic(nlev, ctt, kb_min, tke[b], eps[b], kb[b], Pb[b])
step_kbalgebraic_single = _step_kbalgebraic