Sub-filter kinetic energy equation

The SubFilterKineticEnergyEquation module provides diagnostics for the kinetic energy budget of the sub-filter scales: the scales that a low-pass spatial filter $\widetilde{(\,\cdot\,)}$ removes from the flow. It is the companion of the Filtered kinetic energy equation, which budgets the kinetic energy $K^l = \tfrac{1}{2}\,\tilde v_i\,\tilde v_i$ of the scales the filter keeps.

The sub-filter kinetic energy budget

The sub-filter kinetic energy is half the trace of the sub-filter stress tensor $\tau^r_{ij} = \widetilde{v_i v_j} - \tilde v_i \tilde v_j$ (subfilter_stress_tensor),

\[K^s = \tfrac{1}{2}\,\tau^r_{ii} = \tfrac{1}{2}\left(\tau^r_{11} + \tau^r_{22} + \tau^r_{33}\right) ,\]

computed by SubFilterKineticEnergy. Following the coarse-graining framework of Aluie et al. (2018), its volume-integrated budget (with the transport terms vanishing over a closed or periodic domain) reads

\[\frac{d}{dt} \int K^s\, dV = \int \Pi_K\, dV + \int \tau(w, b)\, dV - \int \varepsilon^s\, dV ,\]

with two sources and one sink:

  • $\Pi_K$ (KineticEnergyCrossScaleFlux) is the cross-scale kinetic-energy flux, the rate at which the filtered scales hand kinetic energy down to the sub-filter scales. It is the sink of the filtered-flow budget and the source of this one.
  • $\tau(w, b) = \widetilde{wb} - \tilde w\,\tilde b$ is the sub-filter buoyancy flux (a subfilter_covariance), which converts sub-filter potential energy into sub-filter kinetic energy.
  • $\varepsilon^s = \widetilde{\varepsilon} - \varepsilon^l$ is the sub-filter dissipation (SubFilterKineticEnergyDissipationRate): the filtered total dissipation $\widetilde{\varepsilon}$ (KineticEnergyDissipationRate) minus the dissipation $\varepsilon^l$ of the filtered flow (FilteredKineticEnergyDissipationRate).

The Rayleigh-Taylor instability example closes this budget for a large-eddy simulation.

Sub-filter kinetic energy

Oceanostics.SubFilterKineticEnergyEquation.SubFilterKineticEnergyType
SubFilterKineticEnergy(model, filter)

Return the sub-filter-scale (SFS) kinetic energy , the kinetic energy carried by the scales that a low-pass filter removes from the flow — the filtered full kinetic energy minus the kinetic energy of the filtered flow:

    Kˢ = filter(K) - Kˡ ,   K = ½ uᵢuᵢ ,   Kˡ = ½ ūᵢūᵢ ,   ūᵢ = filter(uᵢ)

equivalently Kˢ = ½ τⁱⁱ with the sub-filter stress τⁱʲ = filter(uⁱuʲ) - ūⁱūʲ (coarse-graining framework of Aluie et al., 2018, J. Phys. Oceanogr., doi:10.1175/JPO-D-17-0100.1). It is assembled from the full kinetic energy K and FilteredKineticEnergy , which share the same interpolate-the-square (½⟨uᵢ²⟩) discretization, so the discrete decomposition filter(K) = Kˡ + Kˢ holds exactly by construction (on any grid, not just where the filter and interpolation commute).

filter is any callable mapping a field to its low-pass-filtered counterpart, e.g. a reusable GaussianFilter or BoxFilter. The full kinetic energy is materialized as a Field before it is filtered (so the separable filter takes its fast staged path); the result lives at (Center, Center, Center), per unit mass (units m² s⁻²):

using Oceananigans, Oceanostics

grid = RectilinearGrid(size=(4, 4, 4), extent=(1, 1, 1), topology=(Periodic, Periodic, Bounded))
model = NonhydrostaticModel(grid)

filter = GaussianFilter(; dims=(1, 2, 3), σ=0.1)
SubFilterKineticEnergy(model, filter)

# output

SubFilterKineticEnergy KernelFunctionOperation at (Center, Center, Center)
├── grid: 4×4×4 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 3×3×3 halo
├── kernel_function: subfilter_kinetic_energy_ccc (generic function with 1 method)
└── arguments: ("Field", "Field", "Field", "Field")
└── computes: sub-filter kinetic energy  Kˢ = ½τⁱⁱ

A convenience method SubFilterKineticEnergy(model; σ, dims, boundary, N) builds the Gaussian filter for you from a standard deviation σ (with σ = ℓ / (2√(2 ln 2)) for a FWHM ).

source

Sub-filter kinetic energy dissipation

Oceanostics.SubFilterKineticEnergyEquation.SubFilterKineticEnergyDissipationRateType
SubFilterKineticEnergyDissipationRate(model, filter)

Return the sub-filter-scale (SFS) kinetic-energy dissipation rate εˢ, the viscous dissipation carried by the scales that a low-pass filter removes:

    εˢ = filter(ε) - εˡ

where ε is the dissipation rate of the full flow (KineticEnergyDissipationRate) and εˡ is the dissipation rate of the filtered flow (FilteredKineticEnergyDissipationRate). It is the viscous sink in the budget of the sub-filter kinetic energy (SubFilterKineticEnergy; coarse-graining framework of Aluie et al., 2018, J. Phys. Oceanogr., doi:10.1175/JPO-D-17-0100.1). For a constant viscosity it reduces to 2ν[filter(SⁱʲSⁱʲ) - S̄ⁱʲ S̄ⁱʲ] ≥ 0, a strictly positive sink.

filter is any callable mapping a field to its low-pass-filtered counterpart, e.g. a reusable GaussianFilter or BoxFilter. Following the KineticEnergyCrossScaleFlux pattern, the result is a single KernelFunctionOperation whose kernel indexes a pre-assembled operation with materialized filtered Field leaves (the full-flow dissipation ε is materialized before it is filtered, and the filtered result is wrapped in a Field so the separable filter takes its fast staged path). It lives at (Center, Center, Center), per unit mass (units m² s⁻³). The model needs a closure whose viscous fluxes are defined, exactly as FilteredKineticEnergyDissipationRate requires:

using Oceananigans, Oceanostics

grid = RectilinearGrid(size=(4, 4, 4), extent=(1, 1, 1), topology=(Periodic, Periodic, Bounded))
model = NonhydrostaticModel(grid; closure=ScalarDiffusivity(ν=1e-4))

filter = GaussianFilter(; dims=(1, 2, 3), σ=0.1)
SubFilterKineticEnergyDissipationRate(model, filter)

# output

SubFilterKineticEnergyDissipationRate KernelFunctionOperation at (Center, Center, Center)
├── grid: 4×4×4 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 3×3×3 halo
├── kernel_function: subfilter_ke_dissipation_rate_ccc (generic function with 1 method)
└── arguments: ("Oceananigans.AbstractOperations.BinaryOperation",)
└── computes: sub-filter kinetic energy dissipation rate  εˢ = filter(ε) - εˡ

A convenience method SubFilterKineticEnergyDissipationRate(model; σ, dims, boundary, N) builds the Gaussian filter for you from a standard deviation σ (with σ = ℓ / (2√(2 ln 2)) for a FWHM ).

source