API Documentation

Public API

Breeze.Breeze — Module

Julia package for finite-volume GPU and CPU large eddy simulations (LES) of atmospheric flows. The abstractions, design, and finite-volume engine are based on Oceananigans.

source

Advection

Breeze.Advection.bottom_advective_tracer_flux — Method
bottom_advective_tracer_flux(i, j, grid, advection, ρ, w, c)

Compute the downward advective mass flux per unit area at the bottom face (k = 1) for tracer c advected by vertical velocity w through density field ρ, using the given advection scheme.

For an explicit scheme this evaluates the same face flux that div_ρUc uses at the bottom boundary. For adaptive implicit vertical advection it returns the instantaneous split-operator flux at the supplied tracer state; the step-integrated implicit outflow depends on the post-solve tracer and must be accumulated separately.

For adaptive implicit vertical advection, the result includes both the CFL-scaled high-order explicit flux and its first-order implicit remainder, evaluated at c.

Returns a positive value for downward (out-of-domain) flux.

source

AnelasticEquations

Breeze.AnelasticEquations — Module
AnelasticEquations

Module implementing anelastic dynamics for atmosphere models.

The anelastic approximation filters acoustic waves by assuming density and pressure are small perturbations from a dry, hydrostatic, adiabatic reference state. The key constraint is that mass flux divergence vanishes:

\[\boldsymbol{\nabla} ⋅ (ρᵣ \boldsymbol{u}) = 0\]

source
Breeze.AnelasticEquations.AnelasticDynamics — Method
AnelasticDynamics(
    reference_state;
    pressure_solver_float_type=Float64
) -> AnelasticDynamics{<:Any, Nothing, DataType}

Return AnelasticDynamics representing incompressible fluid dynamics expanded about reference_state.

Keyword arguments

  • pressure_solver_float_type: floating-point type of the anelastic pressure solve. Default: Float64, also for a Float32 model. The Fourier–tridiagonal solve is poorly conditioned for the longest horizontal waves under a tall, strongly stratified column, and can be unstable in Float32 on large domains. When it differs from the grid's type, the solver is built on a copy of the grid in this type, and the pressure is returned in the model's precision.
source

AtmosphereModels

Breeze.AtmosphereModels.total_energy_density_name — Constant
total_energy_density_name

The key under which an energy input — a surface heat flux, a diabatic heating rate — is supplied to AtmosphereModel, :ρE, along with its specific alias :E for forcings.

$E$ denotes total energy (total_energy), so the key names the physical input without committing to the variable that carries it: a boundary_conditions or forcing entry keyed ρE is routed onto whichever thermodynamic density the formulation evolves (see thermodynamic_density_name), converted as that variable requires — divided by $ĉᵖ Π$ for $ρθ$, whether it arrives as a flux or as a forcing, and passed through unconverted for $ρs$, which is itself an energy per unit mass.

$s$ names static energy specifically and $e$ is reserved for turbulent kinetic energy, so neither doubles as the energy key: ρs is a valid key only when static energy is the prognostic thermodynamic variable.

source
Breeze.AtmosphereModels.total_moisture_density_name — Constant
total_moisture_density_name

The key under which a water input — a surface evaporative flux, a moisture source — is supplied to AtmosphereModel, :ρqᵗ, along with its specific alias :qᵗ for forcings.

$qᵗ$ denotes total moisture, so the key names the physical input without committing to the variable that carries it: a boundary_conditions or forcing entry keyed ρqᵗ is routed onto whichever moisture density the microphysics evolves (see moisture_prognostic_name). Unlike an energy input, no conversion is involved: water added to the prognostic moisture is water added to $qᵗ$ under every scheme, so the routing is a pure re-key.

The prognostic moisture name is scheme-dependent — :ρqᵛ for non-equilibrium cloud formation, :ρqᵉ for saturation adjustment — and changes with the cloud_formation option of BulkMicrophysics, so keying a surface flux by that name ties a setup to one scheme. ρqᵗ is never itself prognostic and therefore works for any of them.

source
Breeze.AtmosphereModels.AbstractMicrophysicalState — Type
AbstractMicrophysicalState{FT}

Abstract supertype for microphysical state structs.

Microphysical states encapsulate the local microphysical variables (e.g., cloud liquid, rain, droplet number) needed to compute tendencies. This abstraction enables the same tendency functions to work for both grid-based LES and Lagrangian parcel models.

Concrete subtypes should be immutable structs containing the relevant mixing ratios and number concentrations for a given microphysics scheme.

For example, a warm-phase one-moment scheme might define a state with cloud liquid and rain mixing ratios (qᶜˡ, qʳ).

See also microphysical_state, microphysical_tendency.

source
Breeze.AtmosphereModels.AbstractSolarPosition — Type
abstract type AbstractSolarPosition

Abstract supertype for solar-position specifications passed to RadiativeTransferModel. Concrete subtypes determine how cos(θ_z) is computed on each radiation update:

  • ApparentSolarPosition — real-Earth time-varying, computed from the model clock and grid (or explicit) longitude/latitude.
  • DiurnalSolarPosition — idealized diurnal cycle at a fixed latitude and declination, no calendar dependence.
  • FixedCosineZenith — constant cos(θ_z), clock-independent.
source
Breeze.AtmosphereModels.AdiabaticBalancer — Type
struct AdiabaticBalancer{T, S}

Configuration for adiabatic (FV3 na_init) initialization, applied with balance_adiabatically!(model, balancer) or set!(model; balancer = AdiabaticBalancer(...)). Works for both CompressibleDynamics and AnelasticDynamics.

Keyword arguments

  • time_stepping: the time discretization used for the balance excursion (the sponge is always stripped — it is irreversible). CompressibleDynamics only; ignored for AnelasticDynamics (which has a single projection-based scheme). Options:
    • default (DefaultTimeStepping()) — fully-explicit stepping. Memory-minimal (no acoustic substepper; only the aliased Gⁿ/U⁰ tendency storage) and cleanly reversible, but Δt is bounded by the vertical acoustic CFL.
    • nothing — reuse the model's native scheme (e.g. split-explicit), at the cost of rebuilding the acoustic substepper's scratch fields.
    • any time-discretization object — swapped in as-is.
  • Δt: forward/backward step size. nothing (default) auto-derives the vertical-acoustic-CFL step acoustic_cfl_safety · Δz_min / c from the grid and analysis sound speed; pass a number to override.
  • cycles: number of balance cycles (default 1).
  • weight: nudging weight toward the analysis snapshot (default 2 → ⅓ dynamics + ⅔ analysis).
  • with_moisture: if true (default) the moisture density ρqᵉ relaxes with the other prognostics. If false, ρqᵉ is snapshotted before the balance and restored after, so it is preserved exactly — reproducing a graft that returns only (ρ, ρu, ρv, ρw, ρθ).
source
Breeze.AtmosphereModels.AllSkyOptics — Type
struct AllSkyOptics <: Breeze.AtmosphereModels.AbstractOptics

Type representing full-spectrum all-sky (cloudy) radiation using RRTMGP gas and cloud optics, can be used as optics argument in RadiativeTransferModel. Requires using RRTMGP, ClimaComms, NCDatasets.

All-sky radiation includes scattering by cloud liquid and ice particles, requiring cloud water path, cloud fraction, and effective radius inputs from the microphysics scheme.

source
Breeze.AtmosphereModels.ApparentSolarPosition — Type
struct ApparentSolarPosition{C, E} <: AbstractSolarPosition

Time-varying apparent solar position. The cosine of the solar zenith angle is recomputed on each radiation update from the model clock and either the grid's $(λ, φ)$ coordinates (when coordinate === nothing, the default) or an explicit (longitude, latitude) tuple stored in coordinate.

When the model clock holds a floating-point time (in seconds), epoch::DateTime provides the absolute reference against which clock.time is resolved. With a DateTime clock, epoch is ignored.

Fields

  • coordinate::Any: Observer longitude/latitude. Either nothing (use grid coordinates) or a (longitude, latitude) tuple in degrees.

  • epoch::Any: DateTime anchor for floating-point clocks. Either nothing (requires a DateTime clock) or a DateTime.

source
Breeze.AtmosphereModels.ApparentSolarPosition — Method
ApparentSolarPosition(;
    coordinate=nothing,
    epoch=nothing
) -> ApparentSolarPosition{Nothing, Nothing}

Construct an ApparentSolarPosition with optional coordinate and epoch.

julia> using Breeze, Datesjulia> ApparentSolarPosition()ApparentSolarPosition(coordinate=<from grid>, epoch=<from clock>)julia> ApparentSolarPosition(coordinate = (-70.9, 42.5))ApparentSolarPosition(coordinate=(-70.9, 42.5), epoch=<from clock>)julia> ApparentSolarPosition(epoch = DateTime(2024, 1, 1))ApparentSolarPosition(coordinate=<from grid>, epoch=2024-01-01T00:00:00)
source
Breeze.AtmosphereModels.AtmosphereModel — Method
AtmosphereModel(
    grid;
    clock=Clock(grid),
    thermodynamic_constants=ThermodynamicConstants(eltype(grid)),
    formulation=:LiquidIcePotentialTemperature,
    dynamics=nothing,
    velocities=nothing,
    moisture_density=DefaultValue(),
    tracers=tuple(),
    coriolis=nothing,
    boundary_conditions=NamedTuple(),
    forcing=NamedTuple(),
    advection=DefaultValue(),
    momentum_advection=DefaultValue(),
    scalar_advection=DefaultValue(),
    closure=nothing,
    microphysics=nothing,
    timestepper=nothing,
    timestepper_kwargs=NamedTuple(),
    radiation=nothing,
    particles::Union{Nothing, Oceananigans.TimeSteppers.AbstractLagrangianParticles}=nothing
) -> AtmosphereModel{Dyn, Frm, Arc, Tst, Grd, Clk, Thm, Mom, Moi, Nothing, Tmp, Sol, Vel, Trc, Adv, Nothing, Frc, Nothing, Cnd, Sed, Nothing, Nothing, Nothing, Nothing} where {Dyn, Frm, Arc, Tst, Grd, Clk, Thm, Mom, Moi, Tmp, Sol, Vel, Trc, Adv, Frc, Cnd, Sed}

Return an AtmosphereModel that uses the anelastic approximation following Pauluis (2008).

Arguments

  • The default dynamics is AnelasticDynamics.

  • The default formulation is :LiquidIcePotentialTemperature.

  • The default advection scheme is Centered(order=2) for both momentum and scalars. If a single advection is provided, it is used for both momentum and scalars.

  • Alternatively, specific momentum_advection and scalar_advection schemes may be provided. scalar_advection may be a NamedTuple with a different scheme for each respective scalar, identified by name.

  • particles are Lagrangian particles to be advected with the flow, constructed with Oceananigans.LagrangianParticles. Particles are advected with the Cartesian velocities model.velocities once per time step, over the full Δt. Default: nothing. See the "Lagrangian particles" section of the documentation for details, including the treatment on terrain-following grids.

Example

julia> using Breezejulia> grid = RectilinearGrid(size=(8, 8, 8), extent=(1, 2, 3));julia> model = AtmosphereModel(grid)AtmosphereModel{CPU, RectilinearGrid}(time = 0 seconds, iteration = 0)├── grid: 8×8×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 3×3×3 halo├── dynamics: AnelasticDynamics(p₀=101325.0, θ₀=288.0)├── formulation: LiquidIcePotentialTemperatureFormulation├── thermodynamic_constants: ThermodynamicConstants{Float64}├── timestepper: SSPRungeKutta3├── advection scheme:│   ├── momentum: Centered(order=2)│   ├── ρθ: Centered(order=2)│   └── ρqᵛ: Centered(order=2)├── forcing: @NamedTuple{ρu::Returns{Float64}, ρv::Returns{Float64}, ρw::Returns{Float64}, ρθ::Returns{Float64}, ρqᵛ::Returns{Float64}, ρE::Returns{Float64}}├── tracers: ()├── coriolis: Nothing└── microphysics: Nothing

References

Pauluis, O. (2008). Thermodynamic consistency of the anelastic approximation for a moist atmosphere. Journal of the Atmospheric Sciences 65, 2719–2729.

source
Breeze.AtmosphereModels.AtmosphereModelBuoyancy — Type
struct AtmosphereModelBuoyancy{D, F, T, M, MF}

Wrapper struct for computing buoyancy for AtmosphereModel in the context of a turbulence closure. Used to interface with Oceananigans turbulence closures that require buoyancy gradients. The microphysics and its fields are carried so that the moisture mass fractions — condensate included — can be recovered at any grid point through grid_moisture_fractions.

source
Breeze.AtmosphereModels.BackgroundAtmosphere — Type
struct BackgroundAtmosphere{N2, O2, CO2, CH4, N2O, CO, NO2, O3, CFC11, CFC12, CFC22, CCL4, CF4, HFC125, HFC134A, HFC143A, HFC23, HFC32}

Volume mixing ratios (VMR) for radiatively active gases. All values are dimensionless molar fractions.

RRTMGP supports spatially-varying VMR only for H₂O (computed from model moisture) and O₃. All other gases use global mean values.

Fields

  • Constant gases (global mean only): N₂, O₂, CO₂, CH₄, N₂O, CO, NO₂
  • Halocarbons: CFC₁₁, CFC₁₂, CFC₂₂, CCl₄, CF₄
  • Hydrofluorocarbons: HFC₁₂₅, HFC₁₃₄ₐ, HFC₁₄₃ₐ, HFC₂₃, HFC₃₂
  • Spatially-varying: O₃ - can be a constant or a function for height-dependent profiles

Defaults are approximate modern atmospheric values for major gases; halocarbons default to zero.

Note: H₂O is computed from the model's prognostic moisture field, not specified here.

The BackgroundAtmosphere constructor does not require a grid. When passed to RadiativeTransferModel, the O₃ field is materialized using the grid. This allows users to seamlessly switch between constant and function-based concentrations.

source
Breeze.AtmosphereModels.BackgroundAtmosphere — Method
BackgroundAtmosphere(;
    N₂=0.78084,
    O₂=0.20946,
    CO₂=0.00042,
    CH₄=1.8e-6,
    N₂O=3.3e-7,
    CO=0.0,
    NO₂=0.0,
    O₃=standard_ozone_profile,
    CFC₁₁=0.0,
    CFC₁₂=0.0,
    CFC₂₂=0.0,
    CCl₄=0.0,
    CF₄=0.0,
    HFC₁₂₅=0.0,
    HFC₁₃₄ₐ=0.0,
    HFC₁₄₃ₐ=0.0,
    HFC₂₃=0.0,
    HFC₃₂=0.0
) -> BackgroundAtmosphere{Float64, Float64, Float64, Float64, Float64, Float64, Float64, typeof(standard_ozone_profile), Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64, Float64}

Construct a BackgroundAtmosphere with volume mixing ratios for radiatively active gases. All values are dimensionless molar fractions.

RRTMGP supports spatially-varying VMR only for H₂O and O₃. Other gases use global means.

  • Constant gases: Specify as numbers
  • O₃: Can be a Number or Function for height-dependent profiles

Keyword Arguments

  • Constant gases: N₂, O₂, CO₂, CH₄, N₂O, CO, NO₂
  • Halocarbons: CFC₁₁, CFC₁₂, CFC₂₂, CCl₄, CF₄
  • Hydrofluorocarbons: HFC₁₂₅, HFC₁₃₄ₐ, HFC₁₄₃ₐ, HFC₂₃, HFC₃₂
  • Spatially-varying: O₃ (can be Number or Function)

Defaults are approximate modern atmospheric values; halocarbons default to zero, and ozone defaults to standard_ozone_profile (pass O₃ = 0 for an ozone-free atmosphere). Note: H₂O is computed from the model's prognostic moisture field.

Example

julia> using Breezejulia> background = BackgroundAtmosphere(CO₂ = 400e-6)BackgroundAtmosphere with 6 active gases:  N₂ = 0.78084  O₂ = 0.20946  CO₂ = 400.0 ppm  CH₄ = 1.8 ppm  N₂O = 330.0 ppb  O₃ = standard_ozone_profile (generic function with 1 method)julia> tropical_ozone(z) = 30e-9 * (1 + z / 10000);julia> background = BackgroundAtmosphere(CO₂ = 400e-6, O₃ = tropical_ozone)BackgroundAtmosphere with 6 active gases:  N₂ = 0.78084  O₂ = 0.20946  CO₂ = 400.0 ppm  CH₄ = 1.8 ppm  N₂O = 330.0 ppb  O₃ = tropical_ozone (generic function with 1 method)
source
Breeze.AtmosphereModels.CellAdvectionTimescale — Type
CellAdvectionTimescale{F}(
    formulation
) where F -> CellAdvectionTimescale
CellAdvectionTimescale(
    formulation::F
) where F -> CellAdvectionTimescale

A callable that returns the advective timescale of a model restricted to the directions of formulation: HorizontalFormulation() counts only the horizontal advective CFL (dropping the vertical term), ThreeDimensionalFormulation() counts all three directions. Pass it to the cell_advection_timescale keyword of TimeStepWizard / conjure_time_step_wizard!, or as the timescale argument of CFL (CFL(Δt, CellAdvectionTimescale(...))), to control or monitor which directions bind the time step.

The vertical term uses the largest transport speed among the air and every advected sedimenting prognostic (air velocity plus sedimentation velocity), so ThreeDimensionalFormulation() reports the true three-dimensional CFL whether or not the vertical advection is implicit.

source
Breeze.AtmosphereModels.CloudScatteringTables — Type
struct CloudScatteringTables{L, I}

Cloud single-scattering tables for EcCKDOptics: one table per condensed phase, each either a Symbol naming a table shipped with the ecRad data (:mie_droplet for spherical liquid droplets, :baum_general_habit_mixture for the Baum general-habit ice mixture) or a path to a netCDF file in the same format.

Fields:

  • liquid: Liquid droplet scattering table, a Symbol selector or a file path
  • ice: Ice particle scattering table, a Symbol selector or a file path
julia> using Breezejulia> CloudScatteringTables()CloudScatteringTables(liquid=:mie_droplet, ice=:baum_general_habit_mixture)
source
Breeze.AtmosphereModels.DiurnalSolarPosition — Type
DiurnalSolarPosition(
    FT::DataType=Oceananigans.defaults.FloatType;
    latitude,
    declination=0,
    day_length=86400,
    noon_offset=0
)

Construct a DiurnalSolarPosition with sensible defaults: perpetual equinox (declination = 0), 24-hour day (day_length = 86400 s), and noon at the start of the simulation (noon_offset = 0).

The positional argument FT controls the precision of the stored fields and defaults to Oceananigans.defaults.FloatType. Pass FT = Float32 (or set Oceananigans.defaults.FloatType = Float32) to run in Float32:

DiurnalSolarPosition(Float32, latitude = 30)
source
Breeze.AtmosphereModels.DiurnalSolarPosition — Type
struct DiurnalSolarPosition{FT} <: AbstractSolarPosition

Idealized diurnal cycle with no annual variation and no calendar dependence. cos(θ_z) is computed analytically on each radiation update from the model clock (which must be numeric — seconds since the start of the run) as

\[\cos(θ_z) = \sin(φ) \sin(δ) + \cos(φ) \cos(δ) \cos(ω), \qquad ω = \frac{2π}{T_d} (t - t_{\text{noon}})\]

where $φ$ is the (fixed) observer latitude, $δ$ is the (fixed) solar declination, $T_d$ is the day length, and $t_{\text{noon}}$ is the simulation time at which local noon occurs. $ω = 0$ at noon and $ω = ±π$ at local midnight. The result is clamped to be non-negative.

Fields

  • latitude::Any: Observer latitude (degrees).

  • declination::Any: Solar declination (degrees). Zero is perpetual equinox; ±23.5 is perpetual solstice.

  • day_length::Any: Rotation period (seconds). Default 86400 is the Earth day.

  • noon_offset::Any: Simulation time (seconds) at which local noon occurs. Default 0.

Examples

Perpetual equinox at 30°N (default: 24-hour day, noon at $t = 0$):

julia> using Breezejulia> DiurnalSolarPosition(latitude = 30)DiurnalSolarPosition(latitude = 30.0°, declination = 0.0°, day_length = 86400.0 s, noon_offset = 0.0 s)

Perpetual June solstice at 45°N:

julia> using Breezejulia> DiurnalSolarPosition(latitude = 45, declination = 23.5)DiurnalSolarPosition(latitude = 45.0°, declination = 23.5°, day_length = 86400.0 s, noon_offset = 0.0 s)

Fast rotator with a 10-hour day, sun overhead, starting at sunrise:

julia> using Breezejulia> DiurnalSolarPosition(latitude = 0, day_length = 10 * 3600, noon_offset = 5 * 3600)DiurnalSolarPosition(latitude = 0.0°, declination = 0.0°, day_length = 36000.0 s, noon_offset = 18000.0 s)
source
Breeze.AtmosphereModels.EcCKDOptics — Type
EcCKDOptics(
    gas_model=:climate_32x32;
    clouds=nothing,
    lookup_search=nothing
) -> EcCKDOptics{<:Any, Nothing, Nothing}

Construct EcCKDOptics with the reference gas_model (default :climate_32x32) and, for all-sky radiation, CloudScatteringTables as clouds (default nothing: clear sky). lookup_search (default nothing: NumericalRadiation's default) selects how the gas optics tables are bracketed.

source
Breeze.AtmosphereModels.EcCKDOptics — Type
struct EcCKDOptics{M, C, S} <: Breeze.AtmosphereModels.AbstractOptics

Full-spectrum radiation with the ecCKD correlated-k gas optics of Hogan & Matricardi (2022), solved column by column by NumericalRadiation.jl. Can be used as the optics argument of RadiativeTransferModel once the extension is loaded with using NumericalRadiation: NumericalRadiation and using NCDatasets (NumericalRadiation exports its own ThermodynamicConstants, so it is loaded qualified next to using Breeze).

The solved column reaches beyond the top of the grid through a OverlyingAtmosphereColumn, so that the downwelling fluxes at the top of the domain include the emission and absorption of the atmosphere above it.

Fields:

  • gas_model: Gas optics model: a Symbol or String selecting a reference ecCKD model shipped with the ecRad data (:climate_32x32, :climate_64x64, ...), a (longwave = path, shortwave = path) pair of ecCKD definition files, or a preloaded NumericalRadiation gas optics model
  • clouds: CloudScatteringTables for all-sky radiation, or nothing for clear sky
  • lookup_search: the NumericalRadiation.AbstractLookupSearch used to bracket the temperature and Planck-source tables of a gas model read from files, or nothing for NumericalRadiation's default. NumericalRadiation.FixedBinarySearch() has no data-dependent loop exit, which Reactant's while-loop raising needs to differentiate through the gas optics
julia> using Breezejulia> EcCKDOptics()EcCKDOptics├── gas_model: :climate_32x32└── clouds: nothingjulia> EcCKDOptics(:climate_64x64, clouds = CloudScatteringTables())EcCKDOptics├── gas_model: :climate_64x64└── clouds: CloudScatteringTables(liquid=:mie_droplet, ice=:baum_general_habit_mixture)
source
Breeze.AtmosphereModels.FixedCosineZenith — Type
struct FixedCosineZenith{FT} <: AbstractSolarPosition

Constant cosine of the solar zenith angle. The model clock has no effect on the sun position; the shortwave path length is fixed at $1 / \cos(θ_z)$ and the top-of-atmosphere downward shortwave flux is solar_constant * cos_zenith.

This is the appropriate choice for idealized studies (radiative-convective equilibrium, RCE intercomparisons) where a diurnal or annual mean is desired. Common values: $\cos(θ_z) = 0.5$ for diurnal mean at mid-latitudes, $\cos(θ_z) ≈ 0.41$ for the global annual mean.

Fields

  • cos_zenith::Any

Example

julia> using Breezejulia> FixedCosineZenith(0.5)FixedCosineZenith(cos_zenith = 0.5)
source
Breeze.AtmosphereModels.GrayOptics — Type
struct GrayOptics <: Breeze.AtmosphereModels.AbstractOptics

Type representing gray atmosphere radiation (O'Gorman & Schneider 2008), can be used as optics argument in RadiativeTransferModel. Solved by RRTMGP.jl's gray solver, which requires using RRTMGP, ClimaComms, NCDatasets.

References

  • O'Gorman, P. A. and Schneider, T. (2008). The hydrological cycle over a wide range of climates simulated with an idealized GCM. Journal of Climate, 21, 3815–3832.
source
Breeze.AtmosphereModels.HydrostaticallyBalancedDensity — Type
HydrostaticallyBalancedDensity(; surface_pressure = nothing)

Marker passed as the ρ value to set! to set the density in discrete moist hydrostatic balance with the just-set θˡⁱ/qᵛ, by per-column integration of the hydrostatic equation upward from the pressure at the bottom face of each column. For CompressibleDynamics.

When the dynamics carries an ExnerReferenceState, the default anchor is taken from it, so the balanced state and the reference it will be differenced against use the same per-column pressure. Without a reference, the anchor is obtained by reducing the dynamics' $z = 0$ datum to each column's bottom face along its current near-surface thermodynamic state. This matters on a terrain-following grid, where anchoring every column at one scalar instead would leave the cold start with no surface pressure gradient across the terrain.

surface_pressure overrides that anchor with a scalar applied to every column. On a terrain-following grid, prefer the default: a scalar cannot represent the terrain-following surface pressure, and one that disagrees with the reference reintroduces the inconsistency.

Unlike supplying a density field, this guarantees the initial column satisfies the discrete hydrostatic balance (pᵏ − pᵏ⁻¹)/Δz + g(ρᵏ + ρᵏ⁻¹)/2 = 0, so the cold start carries no spurious vertical pressure-gradient force. Combine with compute_reference_state = true (perturbation-form base state) and balancer (nonhydrostatic ρw spin-up) for a full one-call initialization.

The current column solve supports liquid-ice potential-temperature thermodynamics and vapor-only moisture. It rejects nonzero liquid/ice condensate because condensate heat capacity and latent corrections are not yet included in the column integration.

source
Breeze.AtmosphereModels.NothingMicrophysicalState — Type
NothingMicrophysicalState{FT}

A microphysical state with no prognostic variables.

Used for Nothing microphysics and SaturationAdjustment schemes where cloud condensate is diagnosed from the thermodynamic state rather than being prognostic.

source
Breeze.AtmosphereModels.OverlyingAtmosphereColumn — Type
OverlyingAtmosphereColumn(
    FT=Oceananigans.defaults.FloatType;
    top=65000.0,
    layers=40,
    blending_height=1000.0,
    temperature=standard_atmosphere_temperature,
    specific_humidity=standard_specific_humidity,
    ozone_mole_fraction=nothing
) -> OverlyingAtmosphereColumn{<:Any, typeof(standard_atmosphere_temperature), typeof(Breeze.AtmosphereModels.standard_specific_humidity), Nothing, Nothing, Nothing}

Construct a OverlyingAtmosphereColumn of float type FT reaching top (default 65 km) with layers layers (default 40), a blending_height of 1 km for the temperature anchor, and the standard_atmosphere_temperature and standard_specific_humidity profiles.

source
Breeze.AtmosphereModels.OverlyingAtmosphereColumn — Type
struct OverlyingAtmosphereColumn{FT, T, Q, O, B, V}

The atmosphere above the top of the grid, as seen by a column radiation solver.

Radiation is solved on the grid's Nz layers plus layers extension layers stacked from the grid's top face z_top to top, geometrically stretched from a first layer as thick as the grid's top layer: with ratio r between successive layers, Δz₁ (rᴺ - 1) / (r - 1) = top - z_top (see overlying_atmosphere_faces). No layers are added when the grid already reaches top.

The extension temperature follows temperature(z), anchored to the temperature T_top on the grid's top face so that the profile is continuous there and relaxes to temperature(z) over blending_height,

\[Tₑ(z) = temperature(z) + (T_top - temperature(z_top)) exp(-(z - z_top) / blending_height) ,\]

with blending_height = 0 disabling the anchor. Pressure is hydrostatic above the top face, the specific humidity follows specific_humidity(z), and the ozone mole fraction follows ozone_mole_fraction(z), or the O₃ of the BackgroundAtmosphere when ozone_mole_fraction is nothing. Each profile is a number (constant with height) or a function of height. Extension layers are clear.

A radiation model materializes the extension on its grid: the materialized OverlyingAtmosphereColumn also holds the extension's layers and the profiles sampled at their centers, which are nothing until then.

Fields:

  • top: Height of the top of the extended column [m]
  • layers: Number of extension layers between the grid top and top
  • blending_height: Height over which the temperature anchor at the grid top decays [m]; 0 disables it
  • temperature: Temperature profile [K]
  • specific_humidity: Specific humidity profile [kg kg⁻¹]
  • ozone_mole_fraction: Ozone mole fraction profile [mol mol⁻¹], or nothing for BackgroundAtmosphere.O₃
  • bottom: Height of the bottom of the extension, the grid's top face [m]
  • profile_temperature_at_bottom: The temperature profile at bottom [K], from which the anchor measures the grid top's departure
  • Δzᵃᵃᶜ: Thickness of the extension layers, bottom-up [m]
  • zᵃᵃᶜ: Height of the extension layers' centers [m]
  • T: The temperature profile at the layer centers, before anchoring [K]
  • qᵛ: The specific_humidity profile at the layer centers [kg kg⁻¹]
  • O₃: The ozone mole fraction profile at the layer centers [mol mol⁻¹]
julia> using Breezejulia> OverlyingAtmosphereColumn()OverlyingAtmosphereColumn{Float64}├── top: 65000.0 m├── layers: 40├── blending_height: 1000.0 m├── temperature: standard_atmosphere_temperature (generic function with 1 method)├── specific_humidity: standard_specific_humidity (generic function with 1 method)└── ozone_mole_fraction: nothingjulia> OverlyingAtmosphereColumn(Float32, top = 80e3, layers = 60, ozone_mole_fraction = 1e-6)OverlyingAtmosphereColumn{Float32}├── top: 80000.0 m├── layers: 60├── blending_height: 1000.0 m├── temperature: standard_atmosphere_temperature (generic function with 1 method)├── specific_humidity: standard_specific_humidity (generic function with 1 method)└── ozone_mole_fraction: 1.0e-6
source
Breeze.AtmosphereModels.RadiativeTransferModel — Type
RadiativeTransferModel(
    grid::Oceananigans.Grids.AbstractGrid,
    optics,
    constants=nothing;
    kw...
)

Construct a RadiativeTransferModel on grid using the specified optics.

Valid optics types are:

  • GrayOptics() - Gray atmosphere radiation (O'Gorman & Schneider 2008)
  • ClearSkyOptics() - Full-spectrum clear-sky radiation using RRTMGP gas optics
  • AllSkyOptics() - Full-spectrum all-sky (cloudy) radiation using RRTMGP gas and cloud optics
  • EcCKDOptics() - Full-spectrum clear- or all-sky radiation using ecCKD gas optics via NumericalRadiation.jl (requires using NumericalRadiation: NumericalRadiation and using NCDatasets)

The RRTMGP optics require using RRTMGP, ClimaComms, NCDatasets. NumericalRadiation exports its own ThermodynamicConstants, so load it qualified (using NumericalRadiation: NumericalRadiation) next to using Breeze.

The constants argument provides physical constants for the radiative transfer solver.

Solar position

The solar_position keyword controls how the cosine of the solar zenith angle is obtained on each radiation update. See AbstractSolarPosition and its subtypes:

  • ApparentSolarPosition (default) — time-varying, computed from the model clock and grid (or explicit) longitude/latitude. Supports DateTime clocks and floating-point clocks resolved against an epoch.
  • FixedCosineZenith — constant cos(θ_z), clock-independent. Appropriate for idealized radiative-convective equilibrium studies.

Example

julia> using Breeze, Oceananigans.Units, RRTMGP, NCDatasetsjulia> using NumericalRadiation: NumericalRadiationjulia> grid = RectilinearGrid(; size=16, x=0, y=45, z=(0, 10kilometers),                              topology=(Flat, Flat, Bounded));julia> RadiativeTransferModel(grid, GrayOptics(), ThermodynamicConstants();                              surface_temperature = 300,                              surface_albedo = 0.1)RadiativeTransferModel├── solar_constant: 1361.0 W m⁻²├── solar_position: ApparentSolarPosition(coordinate=(0.0, 45.0), epoch=<from clock>)├── surface_temperature: ConstantField(300.0) K├── surface_emissivity: ConstantField(0.98)├── direct_surface_albedo: ConstantField(0.1)└── diffuse_surface_albedo: ConstantField(0.1)julia> RadiativeTransferModel(grid, GrayOptics(), ThermodynamicConstants();                              surface_temperature = 300,                              surface_albedo = 0.1,                              solar_position = FixedCosineZenith(0.5))RadiativeTransferModel├── solar_constant: 1361.0 W m⁻²├── solar_position: FixedCosineZenith(cos_zenith = 0.5)├── surface_temperature: ConstantField(300.0) K├── surface_emissivity: ConstantField(0.98)├── direct_surface_albedo: ConstantField(0.1)└── diffuse_surface_albedo: ConstantField(0.1)julia> RadiativeTransferModel(grid, ClearSkyOptics(), ThermodynamicConstants();                              surface_temperature = 300,                              surface_albedo = 0.1,                              background_atmosphere = BackgroundAtmosphere(CO₂ = 400e-6))RadiativeTransferModel├── solar_constant: 1361.0 W m⁻²├── solar_position: ApparentSolarPosition(coordinate=(0.0, 45.0), epoch=<from clock>)├── surface_temperature: ConstantField(300.0) K├── surface_emissivity: ConstantField(0.98)├── direct_surface_albedo: ConstantField(0.1)└── diffuse_surface_albedo: ConstantField(0.1)julia> RadiativeTransferModel(grid, EcCKDOptics(), ThermodynamicConstants();                              surface_temperature = 300,                              surface_albedo = 0.1)RadiativeTransferModel├── solar_constant: 1361.0 W m⁻²├── solar_position: ApparentSolarPosition(coordinate=(0.0, 45.0), epoch=<from clock>)├── surface_temperature: ConstantField(300.0) K├── surface_emissivity: ConstantField(0.98)├── direct_surface_albedo: ConstantField(0.1)├── liquid_effective_radius: ConstantRadiusParticles{Float64}(1.0e-5)├── ice_effective_radius: ConstantRadiusParticles{Float64}(3.0e-5)├── diffuse_surface_albedo: ConstantField(0.1)├── optics: EcCKDOptics with 32 longwave and 32 shortwave g-points, clear sky└── overlying_atmosphere: 40 layers from 10000.0 m to 65000.0 m

References

  • O'Gorman, P. A. and Schneider, T. (2008). The hydrological cycle over a wide range of climates simulated with an idealized GCM. Journal of Climate, 21, 3815–3832.
source
Breeze.AtmosphereModels.SlowDynamics — Type
struct SlowDynamics{D}

Wrapper type indicating that only "slow" tendencies should be computed.

When computing momentum tendencies with a SlowDynamics-wrapped dynamics, the "fast" terms (pressure gradient and buoyancy) return zero. This is used for split-explicit time-stepping where fast terms are handled separately in an acoustic substep loop.

See also SplitExplicitTimeDiscretization.

source
Breeze.AtmosphereModels.SpeciesBorrowing — Type
struct SpeciesBorrowing{VB} <: Breeze.AtmosphereModels.AbstractNegativeMoistureCorrection

Correct negative moisture produced by advection via same-level species borrowing.

At each grid cell, negative hydrometeors borrow from lighter species in the chain (e.g. rain <- cloud liquid <- vapor). Vertical redistribution of any remaining negative vapor is performed when vertical_borrowing is set to VerticalBorrowing.

For microphysics with number concentrations (categories that subtype AbstractNumberConcentrationCategories), orphaned number concentrations are zeroed and negative number concentrations are clamped after mass borrowing.

See fix_negative_moisture! for details.

Fields

  • vertical_borrowing: nothing (default) or VerticalBorrowing() to enable vertical redistribution
source
Breeze.AtmosphereModels.VerticalBorrowing — Type
struct VerticalBorrowing <: Breeze.AtmosphereModels.AbstractNegativeMoistureCorrection

Redistribute negative vapor vertically within each column via a top-to-bottom sweep that pushes deficits downward, followed by one bottom-to-top borrowing step if the bottom level is still negative.

This scheme can be used on its own to correct the moisture prognostic, or as the second phase of SpeciesBorrowing to clean up any vapor deficit that remains after same-level species borrowing.

Column-integrated moisture is conserved ($Δz$-weighted).

source
Breeze.AtmosphereModels.MicrophysicalProcessRate — Method
MicrophysicalProcessRate(
    model,
    name::Symbol
) -> KernelFunctionOperation{<:Any, <:Any, <:Any, <:Any, T, K, D} where {T, K<:Breeze.Microphysics.PredictedParticleProperties.P3ProcessRateKernelFunction, D<:Tuple}

Return a KernelFunctionOperation at (Center, Center, Center) that evaluates the microphysical process rate called name of model.microphysics (for example :autoconversion, :accretion, :condensation, or :rain_evaporation).

Rates are specific: per unit mass of moist air, in kg kg⁻¹ s⁻¹ for mass transfers and kg⁻¹ s⁻¹ for number transfers. Multiply by the density (for example total_density(model.dynamics)) for a rate per unit volume, whose vertical Integral is a column-integrated rate in kg m⁻² s⁻¹.

Each scheme documents which rates it provides and their sign conventions. Schemes that compute their rates jointly with sink limiters evaluate the limited rates, that is, exactly the rates that drive the model tendencies, at the current model state. The operation is lazy: wrap it in Field to compute and store it, slice it with Field(op; indices), or reduce it with Integral and Average.

Supported schemes: PredictedParticlePropertiesMicrophysics, for which every rate field of P3ProcessRates is available.

Example

using Breezegrid = RectilinearGrid(size=(4, 4, 8), extent=(1e3, 1e3, 1e3))model = AtmosphereModel(grid; microphysics=P3Microphysics())set!(model, θ=290, qᵛ=0.01, qᶜˡ=1e-3)autoconversion = MicrophysicalProcessRate(model, :autoconversion)# outputKernelFunctionOperation at (Center, Center, Center)├── grid: 4×4×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 3×3×3 halo├── kernel_function: P3ProcessRateKernelFunction(:autoconversion,)└── arguments: ()
source
Breeze.AtmosphereModels.advecting_momentum — Method
advecting_momentum(model)

Return the momentum tuple used for momentum advection transport and the continuity equation divergence.

For standard (non-terrain) models, this is model.momentum. For terrain-following coordinates, the vertical component ρw is replaced by the contravariant vertical momentum $\rho \tilde{w}$.

source
Breeze.AtmosphereModels.aerosol_field_names — Method
aerosol_field_names(microphysics) -> Tuple{}

Return the names of prognostic fields that carry aerosol populations for microphysics.

Schemes without prognostic aerosol return an empty tuple by default. Microphysics schemes with prognostic aerosol extend this interface so model components can retain or process those fields without depending on scheme-specific names.

source
Breeze.AtmosphereModels.balance_adiabatically! — Method
balance_adiabatically!(
    model::AtmosphereModel,
    balancer::AdiabaticBalancer
) -> AtmosphereModel

Run adiabatic (FV3 na_init) initialization on model in place: spin the nonhydrostatic state (ρw and the pressure balance) into balance with the analysis fields. balancer is an AdiabaticBalancer (or true for the defaults / false for a no-op). Builds a stripped, memory-sharing twin via adiabatic_balance_twin and runs the low-level balance_adiabatically!(model; Δt, cycles, weight) on it, so the balanced state lands directly in model — no graft, no second field set.

source
Breeze.AtmosphereModels.balance_adiabatically! — Method
balance_adiabatically!(
    model::AtmosphereModel;
    Δt,
    cycles=1,
    weight=2
)

Spin up a balanced vertical momentum ρw (and the nonhydrostatic pressure balance) consistent with model's initial (analysis) state, via FV3 adiabatic initialization (na_init).

Analyses (ERA5, GFS, …) supply the density, momentum, and thermodynamic state but cold-start the vertical velocity w at zero (hydrostatic), so the nonhydrostatic state is out of balance with the rest. Each of cycles cycles entails two symmetric forward/backward dynamics excursions at the same Δt. After each excursion — which lets ρw develop — the initial fields (every prognostic except ρw) are nudged back toward their t = 0 snapshot by the weighted mean

x ← (x + weight·x₀) / (1 + weight)

(default weight = 2 → ⅓ dynamics + ⅔ snapshot). ρw is never snapshotted or nudged, so the balance the excursion imprints on it is exactly what is kept. update_state! after each nudge rebuilds the diagnostics; the clock is reset to t = 0 on exit.

balance_adiabatically! performs adiabatic dynamics only. The caller must pass a model built without physics (microphysics = nothing), without an upper sponge, and without forcing — these run inside update_state!/time_step! and would corrupt the spin-up. Boundary conditions are not modified; pass a model whose boundaries are time-invariant so the symmetric excursion stays nearly reversible. The two-argument balance_adiabatically!(model, balancer) constructs such a model automatically.

source
Breeze.AtmosphereModels.bottom_precipitation_flux — Method
bottom_precipitation_flux(
    model
) -> Field{LX, LY, LZ, O, G, I, D, T, B, Oceananigans.Fields.FieldStatus{Float64}} where {LX, LY, LZ, O, G, I, D, T, B}

Return a 2D Field representing the flux of precipitating moisture at the bottom boundary, in kg/m²/s (positive = downward flux out of domain).

The default sums the bottom-face advective flux of every sedimenting condensate of the model (see materialize_sedimentation), each evaluated with the same advection scheme that transports that tracer, so the diagnostic matches the boundary flux the tendency operator applies. For a scheme whose cloud condensate also sediments (the non-equilibrium 1M and 2M schemes, and P3) this includes cloud droplet and cloud ice fallout, not only rain and snow. For adaptive implicit vertical advection, this is the split-operator flux evaluated at the current state rather than a time-integrated mass-loss diagnostic. Schemes that move precipitation by internal means (such as DCMIP2016KM) extend bottom_precipitation_flux(model, microphysics) instead.

Building the returned Field assembles a kernel operation, so construct it once and compute! it repeatedly rather than calling this inside a callback.

Arguments:

The generic method is implemented in Breeze.Advection, which owns the flux kernel and is loaded after this module.

source
Breeze.AtmosphereModels.buoyancy_forceᶜᶜᶜ — Function
buoyancy_forceᶜᶜᶜ(i, j, k, grid, dynamics, temperature,
                  specific_prognostic_moisture, microphysics, microphysical_fields, constants)

Compute the buoyancy force density $ρ b$ at cell center (i, j, k).

This function is used in the vertical momentum equation to compute the gravitational forcing term.

source
Breeze.AtmosphereModels.compute_forcing! — Method
compute_forcing!(forcing)

Compute any fields or quantities needed by a forcing before it is applied. This function is extended by the Forcings module for forcing types that require pre-computation (e.g., SubsidenceForcing which computes horizontal averages).

source
Breeze.AtmosphereModels.compute_microphysical_tendencies! — Method
compute_microphysical_tendencies!(model)

Add microphysics tendency contributions to the model's Gⁿ fields.

This is the only entry point through which compute_tendencies! adds microphysical sources to the model's Gⁿ fields. Concrete implementations add methods on the two-argument helper compute_microphysical_tendencies!(microphysics, model).

The default implementation launches a single fused kernel that builds the microphysical state ℳ and thermodynamic state 𝒰 once per cell, then +=s the result of microphysical_tendency for each prognostic name into the corresponding G field. Schemes whose tendencies factor naturally per-name only need to extend microphysical_tendency.

Schemes whose tendencies bundle many process rates feeding multiple prognostics (e.g. mixed-phase non-equilibrium 1M, where ~14 process rates feed 5 prognostic tendencies) override this method directly to compute the bundle once per cell.

source
Breeze.AtmosphereModels.condensate_liquid_fraction — Method
condensate_liquid_fraction(microphysics, ::Val)

Return the liquid fraction of the condensate mass name: 1 for liquid, 0 for ice, a number in between for a mass of mixed composition, or nothing (the default) for anything that is not a sedimenting condensate mass.

The fraction must match how moisture_fractions bins the mass into the liquid and ice mass fractions, since those fix the latent heat and heat capacity the thermodynamic state attributes to it. Every name in condensate_field_names with a sedimentation_velocity must declare it; materialize_sedimentation checks this at model construction, since a falling mass without one would leave its latent heat behind. The fraction is the enthalpy the mass carries, not what it falls with: P3's liquid on ice ρqʷⁱ falls at the ice speed yet is liquid, because no fusion enthalpy has been released for it and moisture_fractions counts it in the liquid mass fraction.

The default nothing covers two cases, neither needing a method: condensate that is not a prognostic mass (saturation-adjusted cloud), and a tracer that is not a condensate mass (a number moment such as ρnᶜˡ, or a non-additive property such as P3's ρqᶠ and ρbᶠ). A sedimenting condensate mass with no liquid fraction is an error.

The acoustic substep loop of the compressible core projects the tendency of every name in condensate_field_names onto its pressure with the sensitivity of the mass's phase, so there every such name must declare its fraction, whether or not it sediments.

A mixed-phase particle is normally two condensate masses sharing a fall speed, as P3 carries ice ρqⁱ and the liquid on it ρqʷⁱ. One mass of mixed composition may instead return its liquid fraction, which liquid_fraction_content resolves exactly, the content being linear in composition.

source
Breeze.AtmosphereModels.continuity_density — Function
continuity_density(dynamics)

Return the continuity density: the density whose continuity equation the model solves, $∇·(ρᵣ u) = 0$ on the anelastic core and $∂ₜρᵈ + ∇·(ρᵈ u) = 0$ on the compressible core. Momentum and the thermodynamic variable are stored per unit of it (ρu = ρᵈ u, ρθ = ρᵈ θ), so it is also the divisor for diagnosing velocity (u = ρu/ρᵈ) and potential temperature (θ = ρθ/ρᵈ).

  • AnelasticDynamics: the time-independent reference density ρᵣ.
  • CompressibleDynamics: the prognostic dry-air density ρᵈ.

The total air density ρ = ρᵈ + Σ ρˣ (dry air plus every water species) is a separate quantity, total_density: it recovers the moisture mass fractions (qˣ = ρˣ/ρ) and weights scalar and water advection. The water densities (ρqᵛ, ρqˡ, …) are stored as partial densities (mass per volume), not per unit of the continuity density. On the anelastic core the two densities coincide (total_density === continuity_density).

source
Breeze.AtmosphereModels.default_temperature_solver — Method
default_temperature_solver(dynamics)

Return the default solver for a formulation's temperature inversion given dynamics.

The need for an iterative inversion is dictated by the intersection of the dynamics and the thermodynamic formulation: the fallback returns nothing (closed-form, no iteration), and dynamics whose prognostic closure makes the inversion implicit (e.g. CompressibleDynamics with LiquidIcePotentialTemperatureFormulation, where temperature solves cᵖᵐ T = ĉᵖ (ρ Rᵐ T / pˢᵗ)^κ θ + ℒˡ₀ qˡ + ℒⁱ₀ qⁱ) extend this function to return an iterative solver.

source
Breeze.AtmosphereModels.dynamics_pressure — Function
dynamics_pressure(dynamics)

Return the pressure field appropriate to the dynamical formulation, in Pa — the pressure entering the equation of state, buoyancy, and the thermodynamic tendencies.

For anelastic dynamics, this is the time-independent hydrostatic reference pressure $pᵣ(z)$, excluding the non-hydrostatic pressure anomaly that enforces the divergence constraint but does not perturb the thermodynamic state. For compressible dynamics, this is the diagnosed equation-of-state pressure. The anomaly and total-pressure counterparts are pressure_anomaly and total_pressure.

This is the pressure every physics parameterization should read, including radiation. Call the accessor rather than reaching into dynamics.reference_state directly: which of the two the reference state is varies by formulation. On the anelastic core it is the thermodynamic pressure, and dynamics_pressure returns it. On the compressible core (flat or terrain) it is a pressure-gradient device built once from a fixed profile, it does not track the thermodynamic state, and several dynamics types carry none at all. total_density is the density counterpart.

source
Breeze.AtmosphereModels.grid_moisture_fractions — Method
grid_moisture_fractions(
    i,
    j,
    k,
    grid,
    microphysics,
    ρ,
    qᵛ,
    μ_fields
)

Grid-indexed version of moisture_fractions.

This is the generic wrapper that:

  1. Extracts prognostic values from μ_fields via extract_microphysical_prognostics
  2. Builds the microphysical state via microphysical_state with 𝒰 = nothing
  3. Calls moisture_fractions

This works for non-equilibrium schemes where cloud condensate is prognostic. Non-equilibrium schemes don't need 𝒰 to build their state (they use prognostic fields).

Saturation adjustment schemes should override this to read from diagnostic fields.

source
Breeze.AtmosphereModels.initial_aerosol_number — Method
initial_aerosol_number(microphysics) -> Int64

Return the aerosol population stored in a microphysics scheme's native units.

The units are the scheme's own: a volumetric distribution returns [m⁻³], while a distribution specified per unit mass of air returns [kg⁻¹]. Use initial_aerosol_number_density to obtain the value a prognostic ρnᵃ holds, whichever basis a scheme uses. A scheme may report a population here and carry no ρnᵃ.

Returns 0 by default.

source
Breeze.AtmosphereModels.initial_aerosol_number_density — Method
initial_aerosol_number_density(microphysics, ρ)

Return the default aerosol number density $ρ nᵃ$ [m⁻³] for a microphysics scheme, given the air density ρ (a field for grid models, a number for parcels).

This is the value set! writes into the prognostic field ρnᵃ when the scheme has one and the user supplies neither nᵃ nor ρnᵃ. It is derived from the aerosol size distribution stored in the microphysics scheme, so it stays consistent with the activation parameters. A scheme may report a population here and still have no field to write it to; aerosol_field_names(microphysics) == () is what says so.

Each scheme is responsible for the units of its own aerosol distribution: the density argument is here so that a scheme whose distribution is specified per unit mass [kg⁻¹], as PredictedParticlePropertiesMicrophysics is through AerosolMode.number_mixing_ratio, can return the $ρ$-weighted value that ρnᵃ holds, while a scheme whose distribution is already a volumetric concentration [m⁻³] ignores ρ. Breeze's convention throughout is that nᵃ = ρnᵃ / ρ is per unit mass [kg⁻¹]; a scheme that omits this scaling diagnoses nᵃ with a spurious inverse-density dependence.

By default, forwards to initial_aerosol_number, which returns 0 unless a scheme overrides it.

source
Breeze.AtmosphereModels.is_density_tendency_forcing — Method
is_density_tendency_forcing(_) -> Bool

Return true if forcing produces a density-weighted tendency F_{ρϕ} directly (i.e., already includes the multiplication by ρ).

Forcings that return density tendencies must be supplied under their density-weighted key (e.g., ρθ, ρu) rather than the corresponding specific key (θ, u), because the specific-key dispatch wraps user values in SpecificForcing, which would multiply by ρ a second time. This trait is used by atmosphere_model_forcing to reject such misuses with a clear error.

Defaults to false. Extended for SubsidenceForcing and GeostrophicForcing in the Forcings module.

source
Breeze.AtmosphereModels.materialize_atmosphere_model_boundary_conditions — Function
materialize_atmosphere_model_boundary_conditions(boundary_conditions, grid, formulation,
                                                dynamics, microphysics, thermodynamic_constants,
                                                closure = nothing)

Regularize boundary conditions for an AtmosphereModel. This function is extended by the BoundaryConditions module to provide atmosphere-specific boundary condition handling.

Boundary conditions supplied under the energy key ρE (see total_energy_density_name) are routed onto the prognostic thermodynamic variable of formulation: for :LiquidIcePotentialTemperature they become ρθ boundary conditions, with flux BCs wrapped in EnergyFluxBoundaryCondition to divide by the local mixture heat capacity; for :StaticEnergy they pass through onto ρs unconverted.

Conditions supplied under the moisture key ρqᵗ (see total_moisture_density_name) are likewise routed onto the moisture density that microphysics evolves — ρqᵛ or ρqᵉ, depending on the scheme — without conversion, since water entering the prognostic moisture is water entering $qᵗ$ under any of them.

The dynamics argument provides the standard pressure that boundary conditions need at materialization time.

The microphysics argument specifies the microphysics scheme used to compute moisture fractions for mixture heat capacity and virtual potential temperature calculations.

The turbulence closure sets the gustiness that bulk fluxes constructed without one take: the subgrid turbulent kinetic energy under a TKEBasedTurbulenceClosure, a constant otherwise.

Nothing about the model state is captured here: surface fluxes read the pressure, density, temperature and moisture they need from the model field tuple at evaluation time.

source
Breeze.AtmosphereModels.materialize_atmosphere_model_forcing — Function
materialize_atmosphere_model_forcing(forcing, field, name, model_field_names, context)

Materialize a forcing for an AtmosphereModel field. This function is extended by the Forcings module to handle atmosphere-specific forcing types like subsidence and geostrophic forcings.

The context argument provides additional information needed for materialization, such as grid, reference state, and thermodynamic constants.

source
Breeze.AtmosphereModels.materialize_surface_property — Method
materialize_surface_property(x, grid [, solar_position])

Convert a surface property (albedo, emissivity) to the form the radiative-transfer solver stores: a Number becomes a grid-eltype scalar and a Field passes through. Extend the three-argument form for property sources that must be resolved against the grid and the solar epoch (e.g. an observed-albedo dataset); it falls back to the two-argument form.

source
Breeze.AtmosphereModels.microphysical_state — Method
microphysical_state(microphysics, ρ, μ, 𝒰, velocities)

Build an AbstractMicrophysicalState (ℳ) from density-weighted prognostic microphysical variables μ, density ρ, and thermodynamic state 𝒰.

This is the primary interface that microphysics schemes must implement. It converts density-weighted prognostics to the scheme-specific AbstractMicrophysicalState type.

For non-equilibrium schemes, cloud condensate comes from μ (prognostic fields). For saturation adjustment schemes, cloud condensate comes from 𝒰.moisture_mass_fractions, while precipitation (rain, snow) still comes from μ.

Arguments

  • microphysics: The microphysics scheme
  • ρ: Local density (scalar)
  • μ: NamedTuple of density-weighted prognostic variables (e.g., (ρqᶜˡ=..., ρqʳ=...))
  • 𝒰: Thermodynamic state
  • velocities: NamedTuple of velocity components (; u, v, w) [m/s].

Returns

An AbstractMicrophysicalState subtype containing the local specific microphysical variables.

See also microphysical_tendency, AbstractMicrophysicalState.

source
Breeze.AtmosphereModels.microphysical_tendencies — Method
microphysical_tendencies(
    microphysics,
    names::Tuple,
    ρ,
    ℳ,
    𝒰,
    constants
)

Compute the tendencies of names together, as a tuple in the order given.

The gridless counterpart of compute_microphysical_tendencies!. The default maps microphysical_tendency over names; schemes whose process rates are coupled across species override it to evaluate their bundle once and distribute it.

See also microphysical_tendency, compute_microphysical_tendencies!.

source
Breeze.AtmosphereModels.microphysical_tendency — Method
microphysical_tendency(microphysics, name, ρ, ℳ, 𝒰, constants)

Compute the tendency for microphysical variable name from the microphysical state ℳ and thermodynamic state 𝒰.

This is the state-based tendency interface that operates on scalar states without grid indexing. It works identically for grid-based LES and parcel models.

Arguments

  • microphysics: The microphysics scheme
  • name: Variable name as Val(:name) (e.g., Val(:ρqᶜˡ))
  • ρ: Total density, total_density, which weights the density-weighted prognostics and their tendencies (scalar). Because the prognostic condensate content is $ρ q$, it also sets the precipitation size distributions. On the anelastic core this is the reference density $ρᵣ$.
  • ℳ: Microphysical state (e.g., WarmPhaseOneMomentState)
  • 𝒰: Thermodynamic state
  • constants: Thermodynamic constants

Saturation must not use ρ. The saturation specific humidity $qᵛ⁺ = pᵛ⁺ / (ρᵗʰ Rᵛ T)$ and the supersaturation use the thermodynamic state density density(𝒰, constants), which thermodynamic_state_density also returns: $ρᵗʰ = pᵣ / (Rᵐ T)$ on the anelastic core and the total density on the compressible core.

Returns

The tendency value (scalar, units depend on variable).

See also microphysical_state, AbstractMicrophysicalState.

source
Breeze.AtmosphereModels.microphysical_velocities — Method
microphysical_velocities(
    microphysics,
    microphysical_fields,
    name
) -> Union{Nothing, NamedTuple{(:u, :v, :w), <:Tuple{Oceananigans.Fields.ZeroField{Int64, 3}, Oceananigans.Fields.ZeroField{Int64, 3}, Any}}}

Return the microphysical velocities associated with microphysics, microphysical_fields, and tracer name.

Must be either nothing, or a NamedTuple with three components u, v, w. The velocities are added to the bulk flow velocities for advecting the tracer. For example, the terminal velocity of falling rain.

The generic implementation calls sedimentation_velocity and uses the result as the vertical velocity component.

source
Breeze.AtmosphereModels.moisture_fractions — Method
moisture_fractions(
    ::Nothing,
    ℳ,
    qᵛ
) -> Breeze.Thermodynamics.MoistureMassFractions

Compute MoistureMassFractions from a microphysical state ℳ and scheme-dependent specific moisture $qᵛᵉ$.

The input $qᵛᵉ$ is the scheme-dependent specific moisture: vapor for non-equilibrium schemes, or equilibrium moisture ($qᵉ = qᵛ + qᶜˡ$) for saturation adjustment schemes.

This is the state-based (gridless) interface for computing moisture fractions. Microphysics schemes should extend this method to partition moisture based on their prognostic variables.

The default implementation for Nothing microphysics assumes all moisture is vapor.

source
Breeze.AtmosphereModels.moisture_prognostic_name — Method
moisture_prognostic_name(::Nothing) -> Symbol

Return the prognostic moisture field name as a Symbol for the given microphysics scheme.

The physical meaning of the prognostic moisture field depends on the scheme:

  • Nothing / non-equilibrium: :ρqᵛ (true vapor density)
  • SaturationAdjustment: :ρqᵉ (equilibrium moisture density, diagnostically partitioned)
source
Breeze.AtmosphereModels.precipitation_flux — Method
precipitation_flux(
    model;
    condensates=keys(model.sedimentation)
) -> Union{KernelFunctionOperation{<:Any, <:Any, <:Any, <:Any, T, typeof(Breeze.AtmosphereModels.precipitation_flux_kernel), D} where {T, D<:Tuple{Any, Any}}, KernelFunctionOperation{Center, Center, Face, <:Any, T, typeof(Breeze.AtmosphereModels.precipitation_flux_kernel), D} where {T, D<:Tuple{Any, Any, Any}}}

Return a KernelFunctionOperation at (Center, Center, Face) for the downward mass flux of sedimenting condensate through every $z$-face, in kg m⁻² s⁻¹ (positive downward). Multiply by 3600 to obtain a precipitation rate in mm h⁻¹ of liquid water equivalent.

The flux is the sedimentation part of each condensate's advective mass flux, $-ρ (F(wᵗ + wˢ) - F(wᵗ)) / A_z$, formed with the same advection scheme and face reconstruction that transports the condensate (sedimentation_mass_fluxes plus the adaptive-implicit remainder implicit_sedimentation_mass_fluxes), so it matches the sedimentation the model applies. Here $F(w)$ is the volume-weighted face flux of the condensate's specific humidity at velocity $w$, $wᵗ$ the transport velocity and $wˢ$ the condensate's (negative) sedimentation velocity. At the bottom face, where an impenetrable boundary makes $wᵗ = 0$, it reduces to bottom_precipitation_flux.

The keyword argument condensates selects which sedimenting condensates contribute, by prognostic name (see keys(model.sedimentation)); by default all of them do, which for a scheme with sedimenting cloud condensate includes cloud droplet fallout. Use, for example, condensates = (:ρqʳ,) for the rain flux alone. Sedimentation velocities are those diagnosed during the most recent update_state!.

Example

using Breezegrid = RectilinearGrid(size=(4, 4, 8), extent=(1e3, 1e3, 1e3))model = AtmosphereModel(grid; microphysics=P3Microphysics())set!(model, θ=290, qᵛ=0.01, qᶜˡ=1e-3)P = precipitation_flux(model, condensates=(:ρqʳ,))# outputKernelFunctionOperation at (Center, Center, Face)├── grid: 4×4×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 3×3×3 halo├── kernel_function: precipitation_flux_kernel (generic function with 1 method)└── arguments: ("Tuple", "Field", "Field")
source
Breeze.AtmosphereModels.precipitation_rate — Function
precipitation_rate(model, phase::Symbol=:liquid)

Return a KernelFunctionOperation representing the precipitation rate for the given phase.

The precipitation rate is the rate at which moisture is removed from the atmosphere by precipitation processes.

Arguments:

  • model: An AtmosphereModel with a microphysics scheme
  • phase: Either :liquid (rain) or :ice (snow). Default is :liquid.

Returns a Field or KernelFunctionOperation that can be computed and visualized. Specific microphysics schemes must extend this function.

source
Breeze.AtmosphereModels.prognostic_moisture_phase_fractions — Method
prognostic_moisture_phase_fractions(
    i,
    j,
    k,
    grid,
    microphysics,
    microphysical_fields,
    q
) -> Tuple{Any, Any, Any}

Return the fractions (vapor, liquid, ice) of a change of the prognostic moisture density (moisture_prognostic_name) that each phase takes at fixed temperature, in a cell whose moisture mass fractions are q.

The default is all vapor: a scheme with prognostic condensate carries the vapor as its moisture density. A scheme whose moisture density includes condensate that it diagnoses (saturation adjustment) extends this with the partition its equilibrium gives a change.

The acoustic substep loop of the compressible core projects the moisture tendency onto its pressure with the sensitivities of these phases.

source
Breeze.AtmosphereModels.resolve_column_batch_rows — Method
resolve_column_batch_rows(::Nothing, Ny)

Number of whole j-rows of columns in each radiation batch when the domain's Ny rows are split into at most column_batches batches. nothing means one unbatched solve over all Ny rows.

Batches are whole rows so that each is a contiguous run of columns, and cld(Ny, column_batches) rows each so that every batch has the same width. When those rows do not divide Ny, the domain needs fewer than column_batches batches.

source
Breeze.AtmosphereModels.saturation_adjusted_equilibrium — Method
saturation_adjusted_equilibrium(microphysics)

Return the phase equilibrium to which the scheme adjusts the partition of its prognostic moisture density (moisture_prognostic_name) in saturated air, or nothing if it adjusts none.

The default is nothing: a scheme with prognostic condensate holds the partition it carries. Saturation adjustment returns its equilibrium. In a cell where such a scheme holds cloud condensate (where prognostic_moisture_phase_fractions gives the vapor no share), the pressure that the compressible core re-diagnoses is that of the adjusted partition, in which warming evaporates condensate, and the acoustic substep loop linearizes that pressure.

source
Breeze.AtmosphereModels.sedimentation_composition_increment — Method
sedimentation_composition_increment(
    dynamics,
    q,
    phase
) -> Breeze.Thermodynamics.MoistureMassFractions

Return the change of the moisture mass fractions per unit mass of condensate phase that sediments out of a cell whose mass fractions are q, as a MoistureMassFractions difference vector (the dry-air change is implied by Σq = 1). Continuity advances the continuity density (continuity_density) without a sedimentation source on every core, so the increment depends on what the total density does:

  • fixed (the default; AnelasticDynamics): the total density the mass fractions are referenced to does not respond, so the dry mass fraction qᵈ = 1 − qᵛ − qˡ − qⁱ makes up the departed mass and the increment is q̂ˣ − q̂ᵈ, with q̂ˣ the composition with all mass in x;
  • diagnosed and falling with the condensate (CompressibleDynamics: prognostic dry density ρᵈ, ρ = ρᵈ + Σρˣ): every mass fraction renormalizes and the increment is q̂ˣ − q.

condensate_content differentiates the thermodynamic variable along this increment, ∂φ/∂qˣ = ∇_q φ · Δq: the content per unit falling mass at which the cell the condensate leaves keeps its temperature.

source
Breeze.AtmosphereModels.sedimentation_velocity — Method
sedimentation_velocity(
    microphysics,
    microphysical_fields,
    ::Val
)

Return the sedimentation velocity field (vertical component, [m/s], negative = downward) for the prognostic tracer name, or nothing (the default) if the tracer does not sediment.

Microphysics schemes extend this function for each sedimenting tracer, dispatching on ::Val{name}.

source
Breeze.AtmosphereModels.sedimentation_velocity_field — Method
sedimentation_velocity_field(
    grid
) -> Field{Center, Center, Face, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}

Build a ZFaceField suitable for storing a sedimentation velocity: bottom = nothing ensures a kernel-set bottom-face value is preserved during fill_halo_regions!, while the default impenetrable top holds w = 0 so nothing falls in through the model top.

source
Breeze.AtmosphereModels.set_to_mean! — Method
set_to_mean!(ref::ExnerReferenceState, model)

Exner analogue of the ReferenceState method, for split-explicit CompressibleDynamics. Recompute the base exner_function/pressure/density by re-running the same discrete Exner column integration the constructor uses, with the horizontal-mean liquid-ice potential temperature and vapor mass fraction of the current model state. On height-coordinate grids the recomputed reference is horizontally uniform. Terrain-following model resets use their specialized constant-height mean and per-column integration path.

Unlike the anelastic ReferenceState method there is no rescale_densities option: the Exner reference is only the perturbation-form base state, not the prognostic density (ρᵈ), so changing it does not require rescaling the density-weighted prognostics.

source
Breeze.AtmosphereModels.set_to_mean! — Method
set_to_mean!(
    ref::ReferenceState,
    model;
    rescale_densities=false
)

Recompute the reference pressure and density profiles from horizontally-averaged temperature and moisture mass fractions of the current model state.

When rescale_densities=true, density-weighted prognostic fields (ρs, ρqᵗ, ρu, etc.) are rescaled by ρᵣ_new / ρᵣ_old so that the specific quantities (s, qᵗ, u, etc.) are unchanged. When false (default), the density-weighted fields are left as-is and only diagnostics are recomputed.

source
Breeze.AtmosphereModels.specific_humidity — Method
specific_humidity(model)

Return the specific humidity (vapor mass fraction) field for the given model.

This always returns the actual vapor field $qᵛ$ from the microphysical fields, regardless of microphysics scheme.

source
Breeze.AtmosphereModels.specific_prognostic_moisture — Method
specific_prognostic_moisture(microphysics, qᵗ, μ, ρ)

Convert total specific moisture $qᵗ$ to the scheme-dependent specific moisture $qᵛᵉ$ given the density-weighted microphysical variables μ and the total air density ρ,

\[qᵛᵉ = qᵗ - Σ ρqᶜ / ρ\]

where the sum runs over the independent condensate mass densities named by condensate_field_names. Diagnostic cloud fractions, number concentrations, and dependent moments (such as the P3 rime mass $ρqᶠ$, already contained in $ρqⁱ$) are therefore excluded. Both the values of μ and ρ may be scalars or fields. For Nothing microphysics there is no condensate, so $qᵛᵉ = qᵗ$.

This is used both by set!, to convert a total moisture input, and by parcel models, which carry total moisture $qᵗ$ as their prognostic variable.

Since condensate_field_names is the complement of the prognostic moisture — the same partition total_condensate_density uses — this recovers vapor for non-equilibrium schemes and equilibrium moisture $qᵉ$ for saturation-adjustment schemes, with no per-scheme method needed.

using Breezeusing Breeze.Microphysics: DCMIP2016KesslerMicrophysicsmicrophysics = DCMIP2016KesslerMicrophysics()μ = (ρqᶜˡ=0.0012, ρqʳ=0.0024)specific_prognostic_moisture(microphysics, 0.02, μ, 1.2)# output0.017
source
Breeze.AtmosphereModels.specific_prognostic_moisture — Method
specific_prognostic_moisture(model)

Return the prognostic specific moisture field for model.

This is $qᵛ$ for non-equilibrium schemes or $qᵉ$ for saturation adjustment schemes. To convert total specific moisture instead, pass microphysics, qᵗ, the density-weighted microphysical variables, and the total air density.

source
Breeze.AtmosphereModels.standard_atmosphere_temperature — Method
standard_atmosphere_temperature(z)

The temperature (K) of the U.S. Standard Atmosphere 1976 (NOAA, NASA & USAF (1976)) at height z (m): piecewise linear through the seven layers between 0 and 86 km, with the troposphere cooling at 6.5 K km⁻¹ from 288.15 K at the surface to 216.65 K at 11 km, an isothermal lower stratosphere, warming to 270.65 K at the stratopause (47–51 km), and cooling again through the mesosphere to 186.946 K at 84.852 km. Held constant above that, and z is taken as the geopotential height.

julia> using Breezejulia> standard_atmosphere_temperature(0)288.15julia> standard_atmosphere_temperature(11e3)216.65julia> standard_atmosphere_temperature(50e3)270.65
source
Breeze.AtmosphereModels.standard_ozone_profile — Method
standard_ozone_profile(z)

An idealized climatological ozone volume mixing ratio (mol/mol) as a function of height z (m): a weak tropospheric background increasing toward the tropopause, blended into a Gaussian stratospheric layer peaking near 25 km. Keeps the stratospheric column near radiative balance in deep-column simulations — without ozone the upper column is far from radiative equilibrium and destabilizes when the spectral fluxes recompute. Not a substitute for an observed or model ozone climatology.

source
Breeze.AtmosphereModels.static_energy_density — Function
static_energy_density(model)

Return the static energy density field for the given model.

For LiquidIcePotentialTemperatureFormulation, returns a Field with boundary conditions that convert potential temperature fluxes to energy fluxes. This allows users to use BoundaryConditionOperation to extract energy flux values from the model.

For StaticEnergyFormulation, returns the prognostic energy density field directly.

source
Breeze.AtmosphereModels.thermodynamic_density — Function
thermodynamic_density(formulation)

Return the thermodynamic density field for the given formulation — the prognostic thermodynamic variable in continuity-density-weighted ("flux") form (ρθ, ρs, ρE).

The weighting density is the dynamics' continuity density (see continuity_density): the reference density ρᵣ on the anelastic core and the prognostic dry-air density ρᵈ on the compressible core. The generic name (ρθ) is therefore ρᵈθ on CompressibleDynamics; the intensive variable is recovered as θ = ρθ / continuity_density(dynamics).

source
Breeze.AtmosphereModels.total_density — Method
total_density(
    i,
    j,
    k,
    dry_density,
    microphysics,
    moisture_density,
    microphysical_fields
)

Total air density $ρ = ρᵈ + ρᵗ$ at (i, j, k): the dry-air density dry_density plus the total_condensate_density $ρᵗ$. This is the diagnosed total mass density used where total mass enters the physics — the gravitational/buoyancy term and the equation of state.

source
Breeze.AtmosphereModels.total_density — Method
total_density(dynamics)

Return the model's total air density ρ = ρᵈ + Σρˣ: the density of the model's mass, which converts the stored partial densities to mass fractions ($qˣ = ρqˣ / ρ$) and weights scalar advection, hydrostatics and radiation. CompressibleDynamics diagnoses it from the prognostic dry density and the partial densities. Defaults to continuity_density, so on AnelasticDynamics it is the reference density $ρᵣ(z)$: the anelastic approximation replaces the total density by $ρᵣ$, consistent with the reference pressure $pᵣ$.

Thermodynamic relations of the local state, such as the saturation specific humidity, use thermodynamic_state_density instead.

source
Breeze.AtmosphereModels.transport_velocities — Method
transport_velocities(model)

Return the velocity tuple used for scalar advection transport.

For standard (non-terrain) models, this is model.velocities. For terrain-following coordinates, the vertical component is replaced by the contravariant vertical velocity $\tilde{w}$.

source
Breeze.AtmosphereModels.update_microphysical_auxiliaries! — Function

Update auxiliary microphysical fields at grid point (i, j, k).

This is the single interface function for updating all auxiliary (non-prognostic) microphysical fields. Microphysics schemes should extend this function.

The function receives:

  • μ: NamedTuple of microphysical fields (mutated)
  • i, j, k: Grid indices (after μ since this is a mutating function)
  • microphysics: The microphysics scheme
  • ℳ: The microphysical state at this point
  • ρ: Local density
  • 𝒰: Thermodynamic state
  • constants: Thermodynamic constants

Why i, j, k is needed

Grid indices cannot be eliminated because:

  1. Fields must be written at specific grid points
  2. Some schemes need grid-dependent logic (e.g., k == 1 for bottom boundary conditions in sedimentation schemes)

What to implement

Schemes should write all auxiliary fields in one function. This includes:

  • Specific moisture fractions (qᶜˡ, qʳ, etc.) from the microphysical state
  • Derived quantities (qˡ = qᶜˡ + qʳ, qⁱ = qᶜⁱ + qˢⁿ)
  • Vapor mass fraction qᵛ from the thermodynamic state
  • Terminal velocities for sedimentation

See WarmRainState implementation below for an example.

source
Breeze.AtmosphereModels.validate_schedule — Method
validate_schedule(schedule, arch)

Return schedule if radiation can be updated on it on architecture arch, and throw an ArgumentError otherwise. Every schedule is valid on native architectures; BreezeReactantExt accepts only IterationInterval on ReactantState. AtmosphereModel validates the schedule of its radiation when it is constructed, before anything is traced.

source
Breeze.AtmosphereModels.write_sedimentation_velocity! — Method
write_sedimentation_velocity!(w_field, i, j, k, bc, 𝕎)

Store the fall-speed magnitude 𝕎 diagnosed at cell center (i, j, k) in the sedimentation velocity field w_field at the cell's bottom face: microphysics libraries return positive magnitudes while Breeze stores signed vertical velocities (negative = downward), and sedimentation is always downward, so the donor cell for face k is cell k itself. At k = 1 the precipitation boundary condition bc is applied (see bottom_sedimentation_velocity); the top face (k = Nz + 1) lies outside the :xyz launch region and is held at zero by the impenetrable top boundary condition.

source

AtmosphereModels.Diagnostics

Breeze.AtmosphereModels.Diagnostics.DewpointTemperature — Method
DewpointTemperature(
    model;
    solver=SecantSolver(eltype(model.grid); reltol = 0.0001, abstol = 0, maxiter = 10)
) -> KernelFunctionOperation{<:Any, <:Any, <:Any, <:Any, T, K, D} where {T, K<:Breeze.AtmosphereModels.Diagnostics.DewpointTemperatureKernelFunction, D<:Tuple}

Return a KernelFunctionOperation representing the dewpoint temperature $T⁺$.

The dewpoint temperature is the temperature at which the air would become saturated at its current vapor pressure. It is computed by solving the implicit equation:

\[pᵛ⁺(T⁺) = pᵛ\]

using secant iteration, where $pᵛ$ is the actual vapor pressure and $pᵛ⁺$ is the saturation vapor pressure.

For saturated air, the dewpoint temperature equals the actual temperature.

The solver keyword argument (default SecantSolver(reltol=1e-4, abstol=0, maxiter=10)) controls the secant iteration; its convergence criterion compares the vapor pressure residual against the actual vapor pressure $pᵛ$.

Example

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid; microphysics=SaturationAdjustment())set!(model, θ=300, qᵗ=0.01)T⁺ = DewpointTemperature(model)# outputKernelFunctionOperation at (Center, Center, Center)├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── kernel_function: DewpointTemperatureKernelFunction└── arguments: ()

The result may be wrapped in a Field to store the computed values:

T⁺_field = Field(T⁺)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=289.056, min=287.474, mean=288.266
source
Breeze.AtmosphereModels.Diagnostics.EquivalentPotentialTemperature — Type
EquivalentPotentialTemperature(model, flavor=:specific)

Return a KernelFunctionOperation representing equivalent potential temperature $θᵉ$.

Equivalent potential temperature is conserved during moist adiabatic processes (including condensation and evaporation) and is useful for identifying air masses and tracking convective processes. Following Emanuel1994 equation 4.5.11:

\[θᵉ = T \left(\frac{p₀}{p}\right)^{Rᵈ/cᵖᵐ} \exp\left(\frac{ℒˡ qᵛ}{cᵖᵐ T}\right) ℋ^γ\]

where $ℒˡ$ is the latent heat of vaporization, $qᵛ$ is the vapor mass fraction, $ℋ$ is the relative humidity, and $γ = -Rᵛ qᵛ / cᵖᵐ$.

Arguments

  • model: An AtmosphereModel instance.
  • flavor: Either :specific (default) to return $θᵉ$, or :density to return $ρ θᵉ$.

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid)set!(model, θ=300, qᵗ=0.01)θᵉ = EquivalentPotentialTemperature(model)Field(θᵉ)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=326.162, min=325.851, mean=326.006

References

  • Emanuel, K. A. (1994). Atmospheric Convection. Oxford University Press.
source
Breeze.AtmosphereModels.Diagnostics.LiquidIcePotentialTemperature — Type
LiquidIcePotentialTemperature(model, flavor=:specific)

Return a KernelFunctionOperation representing liquid-ice potential temperature $θˡⁱ$.

Liquid-ice potential temperature is invariant under phase changes at fixed pressure and total water, and accounts for the latent heat associated with liquid water and ice:

\[θˡⁱ = \frac{cᵖᵐ T - ℒˡ₀ qˡ - ℒⁱ₀ qⁱ}{ĉᵖ Π}\]

where $ĉᵖ = qᵈ cᵖᵈ + qᵗ cᵖᵛ$ is the vapor-equivalent heat capacity, $ℒˡ₀$ and $ℒⁱ₀$ are the latent heats extrapolated to absolute zero, $qˡ$, $qⁱ$ are the liquid and ice mass fractions, and $Π$ is the Exner function with the exponent of model.formulation (see Breeze.PotentialTemperatureFormulations.LiquidIcePotentialTemperatureFormulation). This is the variable that LiquidIcePotentialTemperatureFormulation evolves.

Arguments

  • model: An AtmosphereModel instance.
  • flavor: Either :specific (default) to return $θˡⁱ$, or :density to return $ρ θˡⁱ$.

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid)set!(model, θ=300, qᵗ=0.01)θˡⁱ = LiquidIcePotentialTemperature(model)Field(θˡⁱ)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=300.0, min=300.0, mean=300.0
source
Breeze.AtmosphereModels.Diagnostics.PotentialTemperature — Type
PotentialTemperature(model, flavor=:specific)

Return a KernelFunctionOperation representing the (mixture) potential temperature $θ$.

The potential temperature is defined as the temperature a parcel would have if adiabatically brought to a reference pressure $p₀$:

\[θ = \frac{T}{Π}\]

where $T$ is temperature and $Π = (p/p₀)^{Rᵐ/cᵖᵐ}$ is the mixture Exner function, computed using the moist air gas constant $Rᵐ$ and heat capacity $cᵖᵐ$.

Arguments

  • model: An AtmosphereModel instance.
  • flavor: Either :specific (default) to return $θ$, or :density to return $ρ θ$.

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid)set!(model, θ=300, qᵗ=0.01)θ = PotentialTemperature(model)Field(θ)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=300.0, min=300.0, mean=300.0
source
Breeze.AtmosphereModels.Diagnostics.SaturationSpecificHumidity — Type
SaturationSpecificHumidity(
    model,
    flavor_symbol=:prognostic
) -> KernelFunctionOperation{<:Any, <:Any, <:Any, <:Any, T, K, D} where {T, K<:Breeze.AtmosphereModels.Diagnostics.SaturationSpecificHumidityKernelFunction, D<:Tuple}

Return a KernelFunctionOperation representing the specified flavor of saturation specific humidity $qᵛ⁺$.

Flavor options

  • :prognostic

    Return the saturation specific humidity corresponding to the model's prognostic state. This is the same as the equilibrium saturation specific humidity for saturated conditions and a model that uses saturation adjustment microphysics.

  • :equilibrium

    Return the saturation specific humidity in potentially-saturated conditions, using the model's specific moisture field. This is equivalent to the :total_moisture flavor under saturated conditions with no condensate; or in other words, if the specific moisture happens to be equal to the saturation specific humidity.

  • :total_moisture

    Return saturation specific humidity in the case that the total specific moisture is equal to the saturation specific humidity and there is no condensate. This is useful for manufacturing perfectly saturated initial conditions.

source
Breeze.AtmosphereModels.Diagnostics.StabilityEquivalentPotentialTemperature — Type
StabilityEquivalentPotentialTemperature(model, flavor=:specific)

Return a KernelFunctionOperation representing stability-equivalent potential temperature $θᵇ$.

Stability-equivalent potential temperature is a moist-conservative variable suitable for computing the moist Brunt-Väisälä frequency. It follows from the derivation in the paper by Durran and Klemp (1982), who show that the moist Brunt-Väisälä frequency $Nᵐ$ is correctly expressed in terms of the vertical gradient of a moist-conservative variable.

The formulation is based on equation (17) by Durran and Klemp (1982):

\[θᵇ = θᵉ \left( \frac{T}{Tᵣ} \right)^{cˡ qˡ / cᵖᵐ}\]

where $θᵉ$ is the equivalent potential temperature, $T$ is temperature, $Tᵣ$ is the energy reference temperature, $cˡ$ is the heat capacity of liquid water, $qᵗ$ is the total moisture specific humidity, and $cᵖᵐ$ is the moist air heat capacity.

This quantity is conserved along moist adiabats and is appropriate for use in stability calculations in saturated atmospheres.

Arguments

  • model: An AtmosphereModel instance.
  • flavor: Either :specific (default) to return $θᵇ$, or :density to return $ρ θᵇ$.

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid)set!(model, θ=300, qᵗ=0.01)θᵇ = StabilityEquivalentPotentialTemperature(model)Field(θᵇ)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=326.162, min=325.851, mean=326.006

References

  • Durran, D. R. and Klemp, J. B. (1982). On the effects of moisture on the Brunt-Väisälä frequency. Journal of the Atmospheric Sciences 39, 2152–2158.
source
Breeze.AtmosphereModels.Diagnostics.StaticEnergy — Type
StaticEnergy(model, flavor=:specific)

Return a KernelFunctionOperation representing moist static energy $s$.

Moist static energy is a conserved quantity in adiabatic, frictionless flow that combines sensible heat, gravitational potential energy, and latent heat:

\[s = cᵖᵐ T + g z - ℒˡ₀ qˡ - ℒⁱ₀ qⁱ\]

where $cᵖᵐ$ is the moist air heat capacity, $T$ is temperature, $g$ is gravitational acceleration, $z$ is height, and $ℒˡ₀ qˡ + ℒⁱ₀ qⁱ$ uses latent-heat offsets extrapolated to zero kelvin.

This is the prognostic thermodynamic variable used in StaticEnergyThermodynamics.

Arguments

  • model: An AtmosphereModel instance.
  • flavor: Either :specific (default) to return $s$, or :density to return $ρ s$.

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid)set!(model, θ=300)s = StaticEnergy(model)Field(s)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=3.03019e5, min=302661.0, mean=3.0284e5
source
Breeze.AtmosphereModels.Diagnostics.VirtualPotentialTemperature — Type
VirtualPotentialTemperature(model, flavor=:specific)

Return a KernelFunctionOperation representing virtual potential temperature $θᵛ$.

Virtual potential temperature is the temperature that dry air would need to have in order to have the same density as moist air at the same pressure. To define virtual potential temperature, we first note the definition of virtual temperature:

\[Tᵛ = T \left( 1 + δᵛ qᵛ - qˡ - qⁱ \right)\]

where $δᵛ ≡ Rᵛ / Rᵈ - 1$. This follows from the ideal gas law for a mixture, $p = ρ Rᵐ T$, the mixture gas constant $Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ = Rᵈ \left( 1 + δᵛ qᵛ - qˡ - qⁱ \right)$, and the definition of virtual temperature, $p = ρ Rᵈ Tᵛ$, which leads to

\[Tᵛ = T \frac{Rᵐ}{Rᵈ} = T \left( 1 + δᵛ qᵛ - qˡ - qⁱ \right)\]

The virtual potential temperature is defined analogously,

\[θᵛ = T \left( \frac{pˢᵗ}{p} \right)^{Rᵈ/cᵖᵈ} \left( 1 + δᵛ qᵛ - qˡ - qⁱ \right) .\]

Note that $Rᵛ / Rᵈ ≈ 1.608$ for water vapor and a dry air mixture typical to Earth's atmosphere, and that $δᵛ ≈ 0.608$.

using Breezegrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 1e3))model = AtmosphereModel(grid)set!(model, θ=300, qᵗ=0.01)θᵛ = VirtualPotentialTemperature(model)Field(θᵛ)# output1×1×8 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×14 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:11) with eltype Float64 with indices 0:2×0:2×-2:11    └── max=301.82, min=301.8, mean=301.81
source
Breeze.AtmosphereModels.Diagnostics.azimuthal_mean! — Method
azimuthal_mean!(profile, field; center=(0, 0), m=4)

Remap field (on an $(x, y, z)$ grid) onto the radial rings of profile (on an $(r, z)$ grid) about center, in place, by area-weighted binning of m × m sub-cells per Cartesian cell. profile and field must share their vertical grid; the radial rings are profile's uniform x-cells.

source
Breeze.AtmosphereModels.Diagnostics.azimuthal_mean — Method
azimuthal_mean(field; radius, Nr, center=(0, 0), m=4)

Azimuthally average field into radial rings about center = (xc, yc), returning a Field on a one-dimensional-in-radius grid — Bounded in radius, Flat in azimuth, and Bounded in z — with Nr uniform rings spanning $[0, \texttt{radius}]$ and the same vertical grid as field.

Each Cartesian cell is split into an m × m block of sub-cells that are binned by radius, so a cell contributes to every ring it overlaps — uniform sub-sampling is area-weighting, which makes this a first-order conservative remap onto the radial rings (a pragmatic stand-in for a reduction on a true cylindrical grid). The kernel runs on the CPU and the GPU. Larger m resolves the rings more finely and keeps near-center rings populated; any ring that still catches nothing (only when $\texttt{radius}/N_r$ is finer than a sub-cell) is filled with NaN, not zero, so it reads as "no data" and doesn't bias a subsequent radial average.

using Oceananigans, Breezegrid = RectilinearGrid(size=(64, 64, 4), x=(-1, 1), y=(-1, 1), z=(0, 1),                       topology=(Periodic, Periodic, Bounded))c = CenterField(grid)set!(c, (x, y, z) -> 5)            # a constant fieldc̄ = azimuthal_mean(c; radius=1, Nr=8)maximum(c̄)                         # the azimuthal mean of a constant is that constant# output5.0
source

BoundaryConditions

Breeze.BoundaryConditions.BulkDragFunction — Method
BulkDragFunction(;
    direction=nothing,
    coefficient=0.001,
    gustiness=DefaultGustiness(),
    surface_temperature=nothing,
    filtered_velocities=nothing
) -> Breeze.BoundaryConditions.BulkDragFunction{Nothing, Nothing, Float64, Breeze.BoundaryConditions.DefaultGustiness, Nothing, Nothing, Nothing}

Create a bulk drag function for computing wall momentum fluxes using bulk aerodynamic formulas. The momentum flux is computed in the same form as the scalar bulk fluxes,

\[Jᵘ = - ρˢ Cᴰ |U| u\]

where Cᴰ is the drag coefficient, |U| = √(u² + v² + Uᵍ²) is the wind speed tangential to the wall together with the gustiness Uᵍ, u is the velocity component at the first cell face, and ρˢ is the surface density computed from the surface pressure and surface temperature. Monin–Obukhov similarity is a profile law for u (not ρu), so using u here keeps the formulation consistent with the similarity theory underlying Cᴰ.

The drag may be placed on any of the six boundaries of a bounded domain, on either of the two momentum components tangential to that wall: ρu and ρv on the bottom and top, ρv and ρw on the west and east, ρu and ρw on the south and north. The sign above is for the bottom; on every wall the drag removes tangential momentum from the domain.

When a FilteredSurfaceVelocities is supplied via filtered_velocities, every field entering the formula — the wind speed |U|, the velocity u, and the surface-layer virtual potential temperature difference Δθᵥ used in stability — is read from the filtered state. The surface density ρˢ is computed from the (slowly varying) surface temperature and pressure and is not filtered. Temporal filtering of the matching velocity is used to mitigate log-layer mismatch in wall-modeled large-eddy simulations, where the spurious correlation between the instantaneous friction velocity and matching-velocity fluctuations otherwise biases the surface stress (Nishizawa & Kitamura (2018); Shin, Yang & Howland (2025)). Filtering is supported on the bottom boundary only.

Monin–Obukhov consistency

ρˢ is computed from the surface temperature and the live model pressure extrapolated hydrostatically from the first cell center to the bottom face. It is therefore a true surface density that follows both terrain and changes in the model state.

Default surface temperature

If the user does not supply surface_temperature, materialization calls default_drag_surface_temperature(dynamics, …). The default exists for AnelasticDynamics (recovered from the reference state via Exner) but raises for CompressibleDynamics, which has no equivalent reference profile — pass surface_temperature explicitly in that case.

Keyword Arguments

  • direction: The direction of the momentum component (XDirection(), YDirection(), or ZDirection()). If nothing, the direction is inferred from the field location during boundary condition regularization.
  • coefficient: The drag coefficient (default: 1e-3). Can be a constant or a PolynomialCoefficient for wind and stability-dependent transfer coefficients.
  • gustiness: The gustiness Uᵍ added to the resolved wind, in the flux and in a PolynomialCoefficient alike: a number, a TKEGustiness, or the default DefaultGustiness, which the model replaces with a TKEGustiness under a TKEBasedTurbulenceClosure and with 0 otherwise.
  • surface_temperature: Surface temperature, used to compute ρˢ and required when using PolynomialCoefficient with stability correction. Can be a Field, Function, or Number. A function takes the non-Flat coordinates of the wall followed by the time, as for Oceananigans boundary conditions: (x, y, t) on the bottom and top, (y, z, t) on the west and east, (x, z, t) on the south and north. (default: nothing)
  • filtered_velocities: A FilteredSurfaceVelocities for temporally filtered wind speed, near-surface velocity, and θᵥ in the bulk formula. If nothing (default), instantaneous fields are used.
source
Breeze.BoundaryConditions.BulkSensibleHeatFluxFunction — Method
BulkSensibleHeatFluxFunction(;
    coefficient,
    gustiness=DefaultGustiness(),
    surface_temperature,
    filtered_velocities=nothing
)

A bulk sensible heat flux function. The flux is computed as:

\[J = - ρˢ Cᵀ |U| Δϕ\]

where $Cᵀ$ is the transfer coefficient, $|U|$ is the wind speed tangential to the wall, and $Δϕ$ is the difference between the near-wall atmospheric value and the wall value of the thermodynamic variable appropriate to the formulation:

  • For LiquidIcePotentialTemperatureFormulation: $Δϕ = θ - θˢ$ (potential temperature flux).
  • For StaticEnergyFormulation: $Δϕ = s - sˢ$ (static energy flux).

The wall value uses the atmospheric vapor, liquid, and ice fractions at the sampling point, the wall temperature $Tˢ$, and the wall pressure and height. This holds composition fixed when computing sensible heat exchange. When filtering is enabled, the complete difference $Δϕ$ is sampled at the filter height and filtered in time.

Here $pˢ$ is the actual surface pressure, while $pˢᵗ$ is the fixed reference pressure used to define potential temperature.

The flux may be placed on any of the six boundaries of a bounded domain. The sign above is for the bottom; on every wall the flux carries heat into the domain when the wall is warmer than the adjacent air.

The formulation is set automatically during model construction based on the thermodynamic formulation.

Keyword Arguments

  • coefficient: The sensible heat transfer coefficient.
  • gustiness: The gustiness $Uᵍ$ added to the resolved wind, $|U| = \sqrt{u² + v² + Uᵍ²}$, in the flux and in a PolynomialCoefficient alike: a number, a TKEGustiness, or the default DefaultGustiness, which the model replaces with a TKEGustiness under a TKEBasedTurbulenceClosure and with 0 otherwise.
  • surface_temperature: The wall temperature. Can be a Field, a Function, or a Number. Functions are evaluated at the wall at every time step with the non-Flat coordinates of the wall followed by the time, as for Oceananigans boundary conditions: (x, y, t) on the bottom and top, (y, z, t) on the west and east, (x, z, t) on the south and north, and for example (x, t) on the bottom of a grid that is Flat in y.
  • filtered_velocities: Either nothing (default) or FilteredSurfaceVelocities. Note that when filtered_velocities is not nothing, then automatically there is filtering in the scalar fields via FilteredSurfaceScalar with the same parameters (e.g., height, timescale) as filtered_velocities. Filtering is supported on the bottom boundary only.
source
Breeze.BoundaryConditions.BulkVaporFluxFunction — Method
BulkVaporFluxFunction(;
    coefficient,
    gustiness=DefaultGustiness(),
    surface_temperature,
    surface_relative_humidity=1,
    moisture_availability=nothing,
    filtered_velocities=nothing
)

Create a bulk vapor flux function for computing wall moisture fluxes. The flux is computed as:

\[Jᵛ = - ρˢ Cᵛ |U| (qᵛ - qˢ), \qquad qˢ = β ℋˢ qᵛ⁺(Tˢ) + (1 - β) qᵛ,\]

where $Cᵛ$ is the transfer coefficient, $|U|$ is the wind speed tangential to the wall, $qᵛ$ is the near-wall specific humidity, and $qˢ$ is the specific humidity of the air in contact with the wall. Over the wet fraction $β$ of the wall (the moisture_availability) that is the saturation specific humidity $qᵛ⁺$ at the wall temperature $Tˢ$ times the wall relative humidity $ℋˢ$ (unity for a wet wall); over the dry fraction it is the humidity of the air itself, so that $qᵛ - qˢ = β (qᵛ - ℋˢ qᵛ⁺)$ and the flux is $β$ times the flux over a wet wall. When filtering is enabled, the complete difference $qᵛ - ℋˢ qᵛ⁺$ is sampled at the filter height and filtered in time, so the wall humidity and the near-wall humidity are seen at the same times, as for BulkSensibleHeatFluxFunction.

The flux may be placed on any of the six boundaries of a bounded domain. The sign above is for the bottom; on every wall the flux carries vapor into the domain when the wall is moister than the adjacent air.

Keyword Arguments

  • coefficient: The vapor transfer coefficient.
  • gustiness: The gustiness $Uᵍ$ added to the resolved wind, $|U| = \sqrt{u² + v² + Uᵍ²}$, in the flux and in a PolynomialCoefficient alike: a number, a TKEGustiness, or the default DefaultGustiness, which the model replaces with a TKEGustiness under a TKEBasedTurbulenceClosure and with 0 otherwise.
  • surface_temperature: The wall temperature. Can be a Field, a Function, or a Number. Used to compute the saturation specific humidity at the wall. Functions take the non-Flat coordinates of the wall followed by the time, as for Oceananigans boundary conditions.
  • surface_relative_humidity: The relative humidity of the air in contact with the wall, between 0 and 1 (default: 1, a saturated wall). Can be a Field, a Function, or a Number.
  • moisture_availability: The fraction $β ∈ [0, 1]$ of the wall that is wet. nothing (default) takes the value carried by a PolynomialCoefficient coefficient, whose stability correction uses the same surface humidity, and 1 (a wet wall, an ocean) for a constant coefficient. A value that disagrees with a PolynomialCoefficient is an error. The phase of the surface water follows the coefficient in the same way, and is liquid for a constant coefficient.
  • filtered_velocities: Either nothing (default) or FilteredSurfaceVelocities. Note that when filtered_velocities is not nothing, then automatically there is filtering in the scalar fields via FilteredSurfaceScalar with the same parameters (e.g., height, timescale) as filtered_velocities. Filtering is supported on the bottom boundary only.
source
Breeze.BoundaryConditions.DefaultGustiness — Type
DefaultGustiness() -> Breeze.BoundaryConditions.DefaultGustiness

The placeholder gustiness of a bulk-flux boundary condition constructed without one. When the AtmosphereModel materializes its boundary conditions it is replaced by materialize_gustiness: with TKEGustiness when the closure is a TKEBasedTurbulenceClosure, and with a constant gustiness of zero otherwise.

using Breeze.BoundaryConditions: DefaultGustiness, materialize_gustinessmaterialize_gustiness(DefaultGustiness(), nothing)# output0
source
Breeze.BoundaryConditions.EnergyFluxBoundaryConditionFunction — Type
EnergyFluxBoundaryConditionFunction

A wrapper for boundary conditions that converts energy flux to potential temperature flux.

When using LiquidIcePotentialTemperatureFormulation, the prognostic thermodynamic variable is $ρθ$ (potential temperature density). This wrapper allows users to specify energy fluxes (e.g., sensible heat flux in W/m²) which are converted to potential temperature fluxes by dividing by the vapor-equivalent heat capacity $ĉᵖ$ and the Exner function $Π$.

The relationship is:

\[Jᶿ = (ρᵈ / ρ) 𝒬ᵀ / (ĉᵖ Π)\]

where $𝒬ᵀ$ is the energy flux, $Jᶿ$ is the flux of $ρθ = ρᵈ θ$, and $ρᵈ / ρ$ (unity for anelastic dynamics) converts a change of enthalpy per unit total mass into one carried by the dry air. At fixed moisture and pressure $ĉᵖ Π θˡⁱ = cᵖᵐ T - ℒˡ₀ qˡ - ℒⁱ₀ qⁱ$ gives $ĉᵖ Π δθ = cᵖᵐ δT$, so an enthalpy input $𝒬ᵀ = ρ cᵖᵐ \overline{w'T'}$ reaches $θ$ as $Jᶿ = 𝒬ᵀ / (ĉᵖ Π)$. The condensate term cancels, so the conversion holds saturated as well as dry. This is the same conversion the $ρE$ interior forcing and the radiative flux divergence apply. In the same spirit, BulkSensibleHeatFlux refers its wall temperature to $θ$, though at the wall pressure rather than the pressure of the adjacent cell.

The heat capacity and Exner function use moisture fractions from the microphysics scheme and the Exner exponent of the formulation (exner_exponent).

source
Breeze.BoundaryConditions.FilteredSurfaceScalar — Method
FilteredSurfaceScalar(
    grid;
    filter_timescale,
    height=nothing
)

A two-dimensional field storing a temporally filtered near-surface scalar for use in bulk flux boundary conditions. The bulk scalar fluxes store the complete near-wall difference of their scalar ($Δθ$, $Δs$, or $Δqᵛ$), so the wall value is filtered together with the atmospheric value.

The filter update is the same exponential form as FilteredSurfaceVelocities.

Keyword Arguments

  • filter_timescale (required): Filter time scale τ in seconds; must be positive and finite.
  • height: Reference height (m) for scalar evaluation. If nothing, the first grid cell center value is used.
source
Breeze.BoundaryConditions.FilteredSurfaceVelocities — Method
FilteredSurfaceVelocities(
    grid;
    filter_timescale,
    height=nothing
)

Two-dimensional fields storing temporally filtered near-surface velocities and the surface-layer virtual potential temperature difference for use in bulk flux boundary conditions. Filtering the matching velocity mitigates log-layer mismatch in wall-modeled large-eddy simulations by removing the spurious correlation between the instantaneous friction velocity and matching-velocity fluctuations (Nishizawa & Kitamura (2018); Shin, Yang & Howland (2025)).

The filtered velocities ū, v̄ (and the surface-layer difference Δθ̄ᵥ when a stability-dependent bulk coefficient is attached) are updated each time step via an exponential (first-order) filter:

ū ← (ū + ϵ u_new) / (1 + ϵ),     ϵ = Δt / τ

where τ is the filter_timescale. There is no default: τ sets how much of the near-surface variability the wall model sees, so it must be chosen for the flow at hand. For a wall model driven by the instantaneous near-surface state, omit filtered_velocities from the bulk boundary condition instead.

Δθ̄ᵥ filters the result the stability correction needs, $Δθᵥ = θᵥ(z₁) - θᵥˢ$, formed at every update by the attached PolynomialCoefficient from the instantaneous first-cell virtual potential temperature and specific humidity, the surface temperature, the moisture availability and the surface phase. Filtering the one difference rather than each of its inputs stores a single field, and is exact since the filter is linear. When the bulk coefficient carries no stability correction the field is allocated but unused.

Keyword Arguments

  • filter_timescale (required): Filter time scale τ in seconds; must be positive and finite.
  • height: Reference height (m) for velocity evaluation. If nothing (default), the first grid cell center value is used. If a number, velocity is linearly interpolated to that height. (Δθ̄ᵥ is always formed at the first cell center, matching the height at which bulk_coefficient evaluates stability.)
source
Breeze.BoundaryConditions.FittedStabilityFunction — Method
FittedStabilityFunction(
    scalar_roughness_length;
    richardson_number_mapping=RichardsonNumberMapping(typeof(scalar_roughness_length)),
    stability_function=StabilityFunction(typeof(scalar_roughness_length))
) -> FittedStabilityFunction{<:Any, RM, SP} where {RM<:Breeze.BoundaryConditions.RichardsonNumberMapping, SP<:Breeze.BoundaryConditions.StabilityFunction}

Stability correction based on Monin-Obukhov similarity theory using the Li et al. (2010) analytical mapping from bulk Richardson number to the stability parameter $ζ = z/L$.

Uses Hogström (1996) integrated stability functions for unstable conditions and Beljaars & Holtslag (1991) for stable conditions.

Applies structurally correct (and different) corrections for momentum vs scalar transfer:

  • Momentum: $Cᴰ = Cᴰ_N [α / (α - Ψᴰ)]²$
  • Scalar: $Cᵀ = Cᵀ_N [α / (α - Ψᴰ)] [β_h / (β_h - Ψᵀ)]$

where $α = \ln(z/ℓʳ)$, $β_h = \ln(z/ℓʳ_h)$.

FittedStabilityFunction is callable: sf(Riᴮ, α, β) returns the momentum stability correction factor, and sf(Riᴮ, α, β, Val(:scalar)) returns the scalar correction factor.

Arguments

  • scalar_roughness_length: Roughness length for heat/moisture $ℓʳ_h$ (m).

Keyword Arguments

References

  • Beljaars, A. C. M., & Holtslag, A. A. M. (1991). Flux parameterization over land surfaces for atmospheric models. Journal of Applied Meteorology, 30, 327-341.
  • Hogström, U. L. F. (1996). Review of some basic characteristics of the atmospheric surface layer. Boundary-Layer Meteorology, 78, 215-246.
  • Li, Y., Gao, Z., Lenschow, D. H., & Chen, F. (2010). An improved approach for parameterizing surface-layer turbulent transfer coefficients in numerical models. Boundary-Layer Meteorology, 137, 153-165.
source
Breeze.BoundaryConditions.PolynomialCoefficient — Type
PolynomialCoefficient(
    FT=Oceananigans.defaults.FloatType;
    polynomial=nothing,
    roughness_length=0.00015,
    minimum_wind_speed=0.1,
    stability_function=FittedStabilityFunction(FT(roughness_length / 7.3)),
    surface=PlanarLiquidSurface(),
    moisture_availability=1,
    transfer_type=nothing
)

A bulk transfer coefficient that depends on wind speed and atmospheric stability, following Large and Yeager (2009).

The neutral transfer coefficient at 10 m follows the Large and Yeager (2009) form:

\[C^N_{10}(U_h) = a_0 + a_1 U_h + a_2 / U_h\]

where $U_h$ is the wind speed at measurement height $h$. The polynomial evaluates to the coefficient itself; Large and Yeager publish their coefficients in units of $10^{-3}$, a scaling the default polynomials carry explicitly.

The coefficient is adjusted for measurement height using logarithmic profile theory, and stability correction is applied based on the bulk Richardson number.

When polynomial is nothing, the appropriate Large and Yeager (2009) polynomial will be automatically selected based on the boundary condition type:

  • BulkDrag: default_neutral_drag_polynomial = (0.142, 0.076, 2.7) .* 1e-3 for momentum
  • BulkSensibleHeatFlux: default_neutral_sensible_heat_polynomial = (0.128, 0.068, 2.43) .* 1e-3 for sensible heat
  • BulkVaporFlux: default_neutral_latent_heat_polynomial = (0.120, 0.070, 2.55) .* 1e-3 for latent heat

Keyword Arguments

  • polynomial: Tuple (a₀, a₁, a₂) for the polynomial. If nothing, the polynomial is automatically selected by the boundary condition constructor.
  • roughness_length: Surface roughness ℓʳ in meters (default: 1.5e-4, typical for ocean)
  • minimum_wind_speed: Minimum wind speed to avoid singularity in a₂/U term (default: 0.1 m/s)
  • stability_function: Stability correction strategy. Default is FittedStabilityFunction using Li et al. (2010) $Riᴮ → ζ$ mapping with Hogström (1996) / Beljaars & Holtslag (1991) MOST stability functions. The scalar roughness length defaults to roughness_length / 7.3 (typical ocean value). Use nothing to disable stability correction.
  • surface: The phase of the surface water, which selects the saturation specific humidity at the surface in the stability correction: PlanarLiquidSurface() (default), PlanarIceSurface() or PlanarMixedPhaseSurface(liquid_fraction).
  • moisture_availability: The fraction $β ∈ [0, 1]$ of the surface that is saturated (default: 1, an ocean). The surface specific humidity entering the stability correction is $qˢ = β qᵛ⁺(Tˢ) + (1 - β) qᵛ$, with $qᵛ$ the specific humidity of the air in the first cell, so that $β = 0$ describes a dry surface whose virtual potential temperature carries no moisture contribution of its own. See wall_virtual_potential_temperature.

The measurement height is automatically determined from the grid as half the first-cell thickness, the height of its center above the local surface.

Examples

using Breeze.BoundaryConditions: PolynomialCoefficient# Polynomial coefficient with default settingscoef = PolynomialCoefficient()# outputPolynomialCoefficient{Float64}├── polynomial: nothing├── roughness_length: 0.00015 m├── minimum_wind_speed: 0.1 m/s├── surface: PlanarLiquidSurface├── moisture_availability: 1.0└── stability_function: FittedStabilityFunction (Li et al. 2010)
using Breeze.BoundaryConditions: PolynomialCoefficient# With explicit polynomialcoef = PolynomialCoefficient(polynomial = (0.000142, 7.6e-5, 0.0027))# outputPolynomialCoefficient{Float64}├── polynomial: (0.000142, 7.6e-5, 0.0027)├── roughness_length: 0.00015 m├── minimum_wind_speed: 0.1 m/s├── surface: PlanarLiquidSurface├── moisture_availability: 1.0└── stability_function: FittedStabilityFunction (Li et al. 2010)
using Breeze.BoundaryConditions: PolynomialCoefficient# No stability correctioncoef = PolynomialCoefficient(stability_function = nothing)# outputPolynomialCoefficient{Float64}├── polynomial: nothing├── roughness_length: 0.00015 m├── minimum_wind_speed: 0.1 m/s├── surface: PlanarLiquidSurface├── moisture_availability: 1.0└── stability_function: Nothing

References

  • Beljaars, A. C. M., & Holtslag, A. A. M. (1991). Flux parameterization over land surfaces for atmospheric models. Journal of Applied Meteorology, 30, 327-341.
  • Hogström, U. L. F. (1996). Review of some basic characteristics of the atmospheric surface layer. Boundary-Layer Meteorology, 78, 215-246.
  • Large, W., & Yeager, S. G. (2009). The global climatology of an interannually varying air–sea flux data set. Climate dynamics, 33(2), 341-364.
  • Li, Y., Gao, Z., Lenschow, D. H., & Chen, F. (2010). An improved approach for parameterizing surface-layer turbulent transfer coefficients in numerical models. Boundary-Layer Meteorology, 137, 153-165.
source
Breeze.BoundaryConditions.RichardsonNumberMapping — Type
RichardsonNumberMapping(
    FT=Oceananigans.defaults.FloatType;
    stable_unstable_transition=0,
    strongly_stable_transition=0.2,
    aᵘ₁₁=0.045,
    bᵘ₁₁=0.003,
    bᵘ₁₂=0.0059,
    aᵘ₂₁=-0.0828,
    aᵘ₂₂=0.8845,
    bᵘ₃₁=0.1739,
    bᵘ₃₂=-0.9213,
    bᵘ₃₃=-0.1057,
    aʷ₁₁=0.5738,
    aʷ₁₂=-0.4399,
    aʷ₂₁=-4.901,
    aʷ₂₂=52.5,
    bʷ₁₁=-0.0539,
    bʷ₁₂=1.54,
    bʷ₂₁=-0.669,
    bʷ₂₂=-3.282,
    aˢ₁₁=0.7529,
    aˢ₂₁=14.94,
    bˢ₁₁=0.1569,
    bˢ₂₁=-0.3091,
    bˢ₂₂=-1.303
) -> Breeze.BoundaryConditions.RichardsonNumberMapping

Regression coefficients for the non-iterative mapping from bulk Richardson number $Riᴮ$ to the Monin-Obukhov stability parameter $ζ = z/L$, following Li et al. (2010).

The superscripts u, w, s denote unstable, weakly stable, and strongly stable regimes respectively. Subscript indices follow the original paper.

Three regimes:

  • Unstable ($Riᴮ <$ stable_unstable_transition): Eq. (12)
  • Weakly stable (stable_unstable_transition $≤ Riᴮ ≤$ strongly_stable_transition): Eq. (14)
  • Strongly stable ($Riᴮ >$ strongly_stable_transition): Eq. (16)

References

  • Li, Y., Gao, Z., Lenschow, D. H., & Chen, F. (2010). An improved approach for parameterizing surface-layer turbulent transfer coefficients in numerical models. Boundary-Layer Meteorology, 137, 153-165.
source
Breeze.BoundaryConditions.StabilityFunction — Type
StabilityFunction(
    FT=Oceananigans.defaults.FloatType;
    γᴰ=19.3,
    γᵀ=11.6,
    a=1,
    b=2 / 3,
    c=5,
    d=0.35
) -> Breeze.BoundaryConditions.StabilityFunction

Parameters for the integrated Monin-Obukhov stability functions $Ψ^D(ζ)$ and $Ψ^T(ζ)$.

Note: we use superscript D (drag/momentum) and T (temperature/scalar) to match the transfer coefficient notation $Cᴰ$, $Cᵀ$ established in notation.md. In the literature these are commonly written $Ψ_m$ and $Ψ_h$.

For unstable conditions ($ζ < 0$), uses Hogström (1996):

  • $φ^D = (1 - γ^D ζ)^{-1/4}$
  • $φ^T = 0.95(1 - γ^T ζ)^{-1/2}$

For stable conditions ($ζ ≥ 0$), uses Beljaars & Holtslag (1991):

  • $Ψ^D = -[a ζ + b (ζ - c/d) e^{-dζ} + bc/d]$
  • $Ψ^T = -[(1 + 2aζ/3)^{3/2} + b (ζ - c/d) e^{-dζ} + bc/d - 1]$

References

  • Beljaars, A. C. M., & Holtslag, A. A. M. (1991). Flux parameterization over land surfaces for atmospheric models. Journal of Applied Meteorology, 30, 327-341.
  • Hogström, U. L. F. (1996). Review of some basic characteristics of the atmospheric surface layer. Boundary-Layer Meteorology, 78, 215-246.
source
Breeze.BoundaryConditions.TKEGustiness — Type
TKEGustiness(
    FT=Oceananigans.defaults.FloatType;
    coefficient=sqrt(2 / 3),
    minimum=0.5
) -> TKEGustiness

A gustiness $Uᵍ$ estimated from the subgrid turbulent kinetic energy $e$ of a TKEBasedTurbulenceClosure in the cell next to the wall,

\[Uᵍ = \max(c \sqrt{e}, Uᵍ_{min}),\]

where $c$ is the coefficient and $Uᵍ_{min}$ the minimum. The default $c = \sqrt{2/3}$ is the isotropic estimate: for isotropic turbulence $e = (u'^2 + v'^2 + w'^2) / 2$ and the variance of each velocity component is $(2/3) e$, so $c \sqrt{e}$ is the root-mean-square of one horizontal component of the subgrid wind. The default minimum of 0.5 m/s is the floor Large and Yeager (2009) place on the wind speed in their bulk formulas.

The gustiness enters the bulk fluxes through the effective wind $Ũ = \sqrt{u² + v² + Uᵍ²}$, which both the flux and its transfer coefficient see. It requires the prognostic TKE density ρe of a TKEBasedTurbulenceClosure, and is the gustiness a bulk-flux boundary condition takes by default under one (see DefaultGustiness).

Keyword Arguments

  • coefficient: The coefficient $c$ in $Uᵍ = c \sqrt{e}$ (default: $\sqrt{2/3}$).
  • minimum: The floor $Uᵍ_{min}$ on the gustiness, in m/s (default: 0.5).

Example

using BreezeTKEGustiness(minimum=0.2)# outputTKEGustiness{Float64}(coefficient=0.816497, minimum=0.2)
source
Breeze.BoundaryConditions.ThetaFluxBoundaryConditionFunction — Type
ThetaFluxBoundaryConditionFunction

A wrapper for boundary conditions that converts potential temperature flux to energy flux.

When building a diagnostic energy_density field from a PotentialTemperatureFormulation, the boundary conditions on ρθ (potential temperature density) must be converted to energy flux boundary conditions by multiplying by the vapor-equivalent heat capacity $ĉᵖ$ and the Exner function $Π$.

The relationship is:

\[𝒬ᵀ = Jᶿ ĉᵖ Π\]

where $𝒬ᵀ$ is the energy flux and $Jᶿ$ is the potential temperature flux.

source
Breeze.BoundaryConditions.BulkDrag — Method
BulkDrag(; direction=nothing, coefficient=1e-3, gustiness=DefaultGustiness(), surface_temperature=nothing)

Create a FluxBoundaryCondition for wall momentum drag, on any of the six boundaries.

See BulkDragFunction for details.

Examples

using Breezedrag = BulkDrag(coefficient=1e-3, gustiness=0.1)# outputFluxBoundaryCondition: BulkDragFunction(direction=Nothing, coefficient=0.001, gustiness=0.1)

Or with explicit direction, e.g., XDirection() for u:

using Oceananigans.Grids: XDirectionu_drag = BulkDrag(direction=XDirection(), coefficient=1e-3)ρu_bcs = FieldBoundaryConditions(bottom=u_drag)# outputOceananigans.FieldBoundaryConditions, with boundary conditions├── west: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)├── east: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)├── south: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)├── north: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)├── bottom: FluxBoundaryCondition: BulkDragFunction(direction=XDirection(), coefficient=0.001, gustiness=DefaultGustiness())├── top: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)└── immersed: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)

and similarly for YDirection for v. The same condition may be placed on the walls of a closed box; the direction is inferred from the momentum component it is attached to:

drag = BulkDrag(coefficient=1e-3)ρv_bcs = FieldBoundaryConditions(west=drag, east=drag, bottom=drag, top=drag)# outputOceananigans.FieldBoundaryConditions, with boundary conditions├── west: FluxBoundaryCondition: BulkDragFunction(direction=Nothing, coefficient=0.001, gustiness=DefaultGustiness())├── east: FluxBoundaryCondition: BulkDragFunction(direction=Nothing, coefficient=0.001, gustiness=DefaultGustiness())├── south: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)├── north: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)├── bottom: FluxBoundaryCondition: BulkDragFunction(direction=Nothing, coefficient=0.001, gustiness=DefaultGustiness())├── top: FluxBoundaryCondition: BulkDragFunction(direction=Nothing, coefficient=0.001, gustiness=DefaultGustiness())└── immersed: DefaultBoundaryCondition (FluxBoundaryCondition: nothing)
source
Breeze.BoundaryConditions.BulkSensibleHeatFlux — Method
BulkSensibleHeatFlux(; coefficient, gustiness=DefaultGustiness(), surface_temperature)

Create a FluxBoundaryCondition for wall sensible heat flux, on any of the six boundaries.

The bulk formula computes

\[J = -ρˢ Cᵀ |U| Δϕ\]

where $Δϕ$ depends on the thermodynamic formulation: $Δθ$ for potential temperature or $Δs$ for static energy. The formulation is set automatically during model construction.

See BulkSensibleHeatFluxFunction for details.

Example

using BreezeTˢ(x, y, t) = 290 + 2 * sign(cos(2π * x / 20e3))ρE_bc = BulkSensibleHeatFlux(coefficient = 1e-3,                             gustiness = 0.1,                             surface_temperature = Tˢ)# outputFluxBoundaryCondition: BulkSensibleHeatFluxFunction(coefficient=0.001, gustiness=0.1)
source
Breeze.BoundaryConditions.BulkVaporFlux — Method
BulkVaporFlux(; coefficient, surface_temperature, surface_relative_humidity=1,
                moisture_availability=nothing, gustiness=DefaultGustiness())

Create a FluxBoundaryCondition for wall moisture flux, on any of the six boundaries.

The specific humidity of the air in contact with the wall is computed from surface_temperature and surface_relative_humidity (unity by default, a wet wall); moisture_availability is the fraction of the wall that is wet, 1 by default.

See BulkVaporFluxFunction for details.

Example

using BreezeTˢ(x, y, t) = 290 + 2 * sign(cos(2π * x / 20e3))moisture_bc = BulkVaporFlux(coefficient = 1e-3,                            gustiness = 0.1,                            surface_temperature = Tˢ)# outputFluxBoundaryCondition: BulkVaporFluxFunction(coefficient=0.001, gustiness=0.1)
source
Breeze.BoundaryConditions.EnergyFluxBoundaryCondition — Function
EnergyFluxBoundaryCondition(
    flux,
    κ̂=VaporEquivalentExponent()
)

Create a boundary condition that wraps an energy flux and converts it to a potential temperature flux for use with LiquidIcePotentialTemperatureFormulation.

The energy flux is divided by the vapor-equivalent heat capacity $ĉᵖ$ and the Exner function $Π$, and by $ρ / ρᵈ$, to obtain the potential temperature flux: $Jᶿ = (ρᵈ / ρ) 𝒬ᵀ / (ĉᵖ Π)$. The model constructor replaces κ̂ with the Exner exponent of its formulation.

source
Breeze.BoundaryConditions.ThetaFluxBoundaryCondition — Function
ThetaFluxBoundaryCondition(
    flux,
    κ̂=VaporEquivalentExponent()
)

Create a boundary condition that wraps a potential temperature flux and converts it to an energy flux for use with diagnostic energy density fields.

The potential temperature flux is multiplied by the vapor-equivalent heat capacity $ĉᵖ$ and the Exner function $Π$, with Exner exponent κ̂, to obtain the energy flux: $𝒬ᵀ = (ρ / ρᵈ) Jᶿ ĉᵖ Π$.

source

CelestialMechanics

Breeze.CelestialMechanics.cos_solar_zenith_angle — Method
cos_solar_zenith_angle(
    i,
    j,
    grid::RectilinearGrid{<:Any, <:Flat, <:Flat, <:Bounded},
    datetime::Dates.AbstractDateTime
)

Compute the cosine of the solar zenith angle for the grid's location.

For single-column grids with Flat horizontal topology, extracts latitude from the y-coordinate and longitude from the x-coordinate.

source
Breeze.CelestialMechanics.cos_solar_zenith_angle — Method
cos_solar_zenith_angle(
    datetime::Dates.AbstractDateTime,
    longitude,
    latitude
)

Compute the cosine of the solar zenith angle for a given datetime and location.

The solar zenith angle $θ_z$ satisfies:

\[\cos(θ_z) = \sin(φ) \sin(δ) + \cos(φ) \cos(δ) \cos(ω)\]

where:

  • $φ$ is the latitude
  • $δ$ is the solar declination
  • $ω$ is the hour angle

Arguments

  • datetime: UTC datetime
  • latitude: latitude in degrees (positive North)
  • longitude: longitude in degrees (positive East)

Returns

A value between -1 and 1. Negative values indicate the sun is below the horizon.

source
Breeze.CelestialMechanics.equation_of_time — Method
equation_of_time(day_of_year)

Compute the equation of time (in minutes) for a given day of year.

This accounts for the difference between mean solar time and apparent solar time due to the eccentricity of Earth's orbit and the obliquity of the ecliptic.

Uses the approximation by Spencer (1971); see solar_declination.

References

  • Spencer, J. W. (1971) Fourier series representation of the position of the sun. Search, 2, 162-172.
source
Breeze.CelestialMechanics.hour_angle — Method
hour_angle(datetime::Dates.AbstractDateTime, longitude)

Compute the hour angle (in radians) for a given datetime and longitude.

The hour angle $ω$ is zero at solar noon and increases by 15° per hour (Earth rotates 360°/24h = 15°/h).

Arguments

  • datetime: UTC datetime
  • longitude: longitude in degrees (positive East)
source
Breeze.CelestialMechanics.solar_declination — Method
solar_declination(day_of_year)

Compute the solar declination angle (in radians) for a given day of year.

Uses the approximation by Spencer (1971):

\[δ = 0.006918 - 0.399912 \cos(γ) + 0.070257 \sin(γ) - 0.006758 \cos(2γ) + 0.000907 \sin(2γ) - 0.002697 \cos(3γ) + 0.00148 \sin(3γ)\]

where $γ = 2π (d - 1) / 365$ is the fractional year in radians and $d$ is the day of year.

References

  • Spencer, J. W. (1971) Fourier series representation of the position of the sun. Search, 2, 162-172.
source

CompressibleEquations

Breeze.CompressibleEquations — Module
CompressibleEquations

Module implementing fully compressible dynamics for atmosphere models.

The compressible formulation directly time-steps density as a prognostic variable and computes pressure from the ideal gas law. This formulation does not filter acoustic waves, so explicit time-stepping with small time steps (or acoustic substepping) is required.

The fully compressible Euler equations in conservation form are:

\[\begin{aligned} &\text{Mass:} && \partial_t \rho + \boldsymbol{\nabla \cdot} (\rho \boldsymbol{u}) = 0 \\ &\text{Momentum:} && \partial_t (\rho \boldsymbol{u}) + \boldsymbol{\nabla \cdot} (\rho \boldsymbol{u} \boldsymbol{u}) + \boldsymbol{\nabla} p = -\rho g \hat{\boldsymbol{z}} + \rho \boldsymbol{f} + \boldsymbol{\nabla \cdot \mathcal{T}} \end{aligned}\]

Pressure is computed from the ideal gas law:

\[p = \rho R^m T\]

where $R^m$ is the mixture gas constant.

source
Breeze.CompressibleEquations.AbstractRamp — Type
abstract type AbstractRamp

Abstract supertype for upper-sponge ramp shapes. A concrete AbstractRamp is callable as (ramp)(z, sponge_top, depth) and returns a value in $[0, 1]$, rising monotonically to one at the lid $z = z_{\rm sponge\_top}$.

Most shapes have compact support, meaning they are exactly zero below the layer base $z_{\rm sponge\_top} - \text{depth}$; GaussianRamp deliberately does not, and instead carries a weak tail all the way down.

Choose a shape on absorption behaviour alone. UpperSponge evaluates the ramp once per z-face at construction and stores the resulting 1D profile, so the substep loop never sees the shape, however expensive it is to evaluate.

source
Breeze.CompressibleEquations.AcousticOuterScheme — Type
abstract type AcousticOuterScheme

Abstract supertype for the outer Runge–Kutta scheme that drives the acoustic substep loop. The current implementation supports a single concrete subtype:

The interface exists to make the outer-scheme commitment explicit in the type system and to provide a clean extension point for a future Multirate Infinitesimal Step (MIS) outer scheme. A concrete subtype is expected to provide a stage_fractions method returning its stage-fraction tuple.

source
Breeze.CompressibleEquations.AcousticSubstepDistribution — Type
abstract type AcousticSubstepDistribution

Abstract supertype for the choice of how acoustic substeps are distributed across the three Wicker–Skamarock RK3 stages.

Concrete subtypes:

  • ProportionalSubsteps — each stage independently covers its own interval $β Δt$ with $Nτ = ⌈β N⌉$ substeps of size $Δτ = β Δt / Nτ$ (count proportional to the stage fraction; size fitted so the substeps exactly tile $β Δt$). This is the default.

  • ConstantSubstepSize — every stage uses the same substep size $Δτ = Δt/N$ ($N$ rounded up to a multiple of 6 so $β N$ is integral), with stage-dependent counts $Nτ = β N$.

  • MonolithicFirstStage — stage 1 collapses to a single substep of size $Δt/3$; stages 2 and 3 are the same as ConstantSubstepSize.

source
Breeze.CompressibleEquations.AcousticSubstepper — Type
struct AcousticSubstepper{N, FT, D, AD, US, CF, TD, MP, TAV, GT, TS, WC, DC, TWC, IS}

Storage and parameters for the split-explicit acoustic substepper (scheme described in the module header). θᴸ=ρθᴸ/ρᴸ and Cᴸ are cached once per stage (recomputing inline per call is much slower on H100); ρᴸ, ρθᴸ, pᴸ and the stage-entry momenta are read live from model.dynamics.* / model.momentum.* (untouched by the loop) and are the recovery base for _recover_full_state! — no snapshot fields. The vertical solve is a (possibly off-centered) Crank-Nicolson tridiagonal Schur system for (ρw)′.

Fields:

  • substeps: acoustic substeps N per Δt (nothing ⇒ adaptive via acoustic_cfl).
  • acoustic_cfl: target horizontal acoustic Courant number for the adaptive count (default 0.5).
  • minimum_horizontal_spacing: the grid's smallest horizontal spacing, which the adaptive count measures the acoustic Courant number against; computed once, when the substepper is built.
  • forward_weight: CN off-centering ω (0.5 = centered; default 0.65).
  • damping, substep_distribution: divergence-damping strategy; substep allocation across WS-RK3 stages.
  • linearization_potential_temperature (θᴸ), linearization_pressure_coefficient (Cᴸ, the slope ∂p/∂(ρθ) of the equation of state at the stage-entry state): per-stage caches, see refresh_linearization_basic_state!.
  • density_perturbation (ρ′), density_potential_temperature_perturbation ((ρθ)′), momentum_perturbation ((ρu/v/w)′ as .u/.v/.w): perturbation prognostics advanced in the loop.
  • density_predictor, density_potential_temperature_predictor: explicit predictors before the vertical solve.
  • previous_density_potential_temperature_perturbation: prior-substep (ρθ)′, for Klemp 2018 damping.
  • time_averaged_velocities: acoustic-mean velocity for non-acoustic scalar transport (moisture/tracers/ chemistry/TKE); the slow ρθ tendency uses the current RK predictor velocity instead, not this cache.
  • slow_vertical_momentum_tendency (Gˢρw, z-faces): advection+Coriolis+closure+forcing (PGF/buoyancy excluded — those are in the fast operator).
  • vertical_solver_source_term (z-faces): explicit RHS of the (ρw)′ tridiagonal system.
  • vertical_solver: factorized BatchedTridiagonalSolver of the implicit (ρw)′ update, factored once per stage (factor_vertical_solver!) so that each substep solves by substitution.
  • vertical_velocity_cache, density_cache: the stage-entry predictor velocity and the dry density that weights it, frozen for implicit_substep! (see cache_advecting_state!); nothing without adaptive-implicit advection.
  • time_averaged_vertical_velocity_cache: the acoustic-mean transport velocity the moisture and tracer tendencies were built with, frozen for scalar_substep! and for the thermodynamic tendency's condensate sedimentation term (see cache_transport_velocity!).
source
Breeze.CompressibleEquations.AcousticSubstepper — Method
AcousticSubstepper(
    grid,
    split_explicit::SplitExplicitTimeDiscretization;
    prognostic_momentum=nothing,
    substep_floattype=eltype(grid),
    cache_advecting_state=false
)

Construct an AcousticSubstepper with auxiliary BCs for perturbations and transport velocities. Bounded normal faces default to nothing; the loop explicitly zeros lateral momentum perturbations. Prescribed flow stays in the stage-entry state, with prognostic BCs reapplied after stage recovery. Inheriting momentum BCs would impose full-state targets on perturbations (issue #716) and velocities. The prognostic_momentum kwarg is retained for backwards compatibility but no longer consulted.

source
Breeze.CompressibleEquations.CompressibleDynamics — Type
struct CompressibleDynamics{TD, D, DT, P, FT, RS, TM, CV, CM}

Fully compressible dynamics with prognostic density and diagnostic pressure.

Fields

  • dry_density: Prognostic dry-air density field ρᵈ
  • total_density: Diagnosed total air density ρ = ρᵈ + Σρˣ (used for thermodynamics, scalar advection, EOS, buoyancy)
  • pressure: Diagnostic pressure field p = ρ Rᵐ T
  • standard_pressure: Reference pressure pˢᵗ for potential temperature (default 10⁵ Pa)
  • base_pressure: Mean pressure of the reference atmosphere at $z = 0$ (p₀). The pressure at the ground is surface_pressure, which the reference state derives from it
  • time_discretization: Time discretization scheme (SplitExplicitTimeDiscretization or ExplicitTimeStepping)
  • reference_state: The single fixed hydrostatically-balanced reference state for base-state pressure/buoyancy correction (perturbation-form PGF), or nothing when disabled. An ExnerReferenceState whose fields are grid-polymorphic: a 1D column on height-coordinate grids, and horizontally-varying 3D fields on terrain-following grids (where a single column is not hydrostatically consistent per terrain column).
  • terrain_metrics: TerrainMetrics for terrain-following coordinates (or nothing). This — not reference_state — is the sole "is this a terrain grid?" signal.
  • w̃, ρw̃: contravariant vertical velocity / momentum diagnostic fields (or nothing when no terrain metrics)

The time_discretization determines how tendencies are computed and which time-stepper is used:

The moist equation-of-state θˡⁱ→T temperature inversion is controlled by the thermodynamic formulation, not the dynamics: see temperature_solver on LiquidIcePotentialTemperatureFormulation.

source
Breeze.CompressibleEquations.CompressibleDynamics — Method
CompressibleDynamics(
    time_discretization::TD=ExplicitTimeStepping();
    standard_pressure=100000.0,
    base_pressure=101325.0,
    reference_potential_temperature=nothing,
    reference_temperature=nothing,
    reference_vapor_mass_fraction=nothing,
    slope_stencil=SlopeOutsideInterpolation(),
    terrain_metrics=nothing,
    reference_state=:auto,
    temperature_tolerance=nothing,
    temperature_maxiter=nothing,
    surface_pressure=nothing
) where TD -> CompressibleDynamics{<:Any, Nothing, Nothing, Nothing, Float64, Breeze.CompressibleEquations.AutoReference, SlopeOutsideInterpolation, Nothing, Nothing}

Construct CompressibleDynamics. The density and pressure fields are materialized later in the model constructor.

Positional Arguments

Keyword Arguments

  • standard_pressure: Reference pressure for potential temperature (default: 10⁵ Pa)

  • base_pressure: Mean pressure of the reference atmosphere at $z = 0$ (default: 101325.0 Pa). A datum, not the pressure at the ground: over terrain, or on a domain whose bottom is raised, the two differ by $O(ρgh)$

  • reference_potential_temperature: Potential temperature for building a fixed hydrostatically-balanced reference state used in base-state subtraction. Can be a constant θ₀ or a function θ(z). Default: nothing, which uses the automatic θᵣ = 288 K profile when reference_state = :auto. When provided, this profile replaces the automatic profile when building the ExnerReferenceState.

  • reference_vapor_mass_fraction: Optional vapor mass fraction for building a moist compressible reference state. Can be a constant qᵛ, function qᵛ(z), or field, and is used with reference_potential_temperature.

  • slope_stencil: Pressure-gradient slope-interpolation stencil for terrain-following grids. Default: SlopeOutsideInterpolation. Ignored on non-terrain-following grids.

  • terrain_metrics: Escape hatch — pass a pre-built TerrainMetrics to bypass the automatic build. Default: nothing (auto-build from the grid using slope_stencil).

  • reference_state: Whether to carry the single hydrostatic reference state used for the perturbation-form pressure-gradient force and buoyancy. Default: :auto — on a bounded vertical grid, build a standard-atmosphere (θᵣ = 288 K) hydrostatic reference: a 1D column on height-coordinate grids, 3D fields on terrain-following grids. Periodic and flat vertical topologies carry no automatic reference because a nontrivial hydrostatic atmosphere is incompatible with periodicity and unnecessary without a vertical dimension. Pass reference_state = nothing to disable it entirely — the PGF and buoyancy then difference the full pressure, reproducing the un-corrected behavior (useful for testing). Disabling is mutually exclusive with an explicit reference profile. To replace the reference with one deduced from an initial state's horizontal mean, call set!(model; …, compute_reference_state=true).

    Deep near-isentropic reference profiles

    The reference integrates the hydrostatic equation up each column using θᵣ(z). A (nearly) constant-θ column is isentropic and its hydrostatic pressure reaches zero at a finite height (≈ cᵖ θ / g, about 29 km for the default θᵣ = 288 K); if the domain top exceeds that height the integration has no positive-pressure solution and the reference fills with NaN. Physical, stably-stratified profiles are unaffected. For such a deep, near-isentropic setup pass either a stratified reference_potential_temperature or reference_state = nothing (full-pressure form).

source
Breeze.CompressibleEquations.ConstantSubstepSize — Type
struct ConstantSubstepSize <: AcousticSubstepDistribution

Acoustic substep distribution where every stage uses the same substep size $Δτ = Δt/N$. $N$ is rounded up to a multiple of 6 (= LCM of the WS-RK3 stage denominators 2 and 3) so the per-stage count $Nτ = β_\mathrm{stage} N$ is an exact integer and each stage covers exactly $β Δt$ — uniform Δτ, at the cost of over-resolving (substep count is the next multiple of 6 ≥ the CFL minimum).

source
Breeze.CompressibleEquations.CubicRamp — Type
struct CubicRamp <: AbstractRamp

Hermite cubic "smoothstep" sponge ramp. $s² (3 − 2s)$ where $s = \text{clamp}((z − (H − \text{depth}))/\text{depth}, 0, 1)$.

Has zero derivative at both the layer base and the lid, so absorbs upgoing waves smoothly without the reflective kink of LinearRamp. Functionally equivalent to Sin2Ramp. The default, and the shape to prefer when the dynamics just below the sponge must be provably untouched; see GaussianRamp for the trade against far-field cleanliness.

source
Breeze.CompressibleEquations.DirectDivergenceDamping — Type
struct DirectDivergenceDamping{FT} <: AcousticDampingStrategy

Acoustic divergence damping that forms the horizontal θ-flux divergence $δ = ∂ₓ(θᴸ(ρu)′) + ∂_y(θᴸ(ρv)′)$ directly from the perturbation momentum, rather than approximating it through the $(ρθ)′$ substep tendency the way ThermalDivergenceDamping does (Klemp, Skamarock & Ha 2018, their eq. 36). After each acoustic substep the horizontal perturbation momentum receives the correction

\[Δ(ρu)′ = α\, Δx²\, ∂ₓ δ / θᴸ, \qquad Δ(ρv)′ = α\, Δy²\, ∂_y δ / θᴸ,\]

with the single dimensionless coefficient α (MPAS config_smdiv, default 0.1; the Laplacian-diffusion stability bound is α ≲ 0.2). The divergence is horizontal only: the damped quantity must match the divergence in the $Θ = ρθ$ equation, and folding in the vertical θ-flux divergence damps the resolved vertical flux and destabilizes the flow. Differencing the velocity field directly (rather than the $(ρθ)′$ tendency) carries no $1/Δτ$ in the diffusivity, which also avoids the thermal proxy's cold-start $∝ α/Δτ$ spurious force (cf. PR #794).

source
Breeze.CompressibleEquations.ExplicitTimeStepping — Type
struct ExplicitTimeStepping

Standard explicit time discretization for compressible dynamics.

All tendencies (including pressure gradient and acoustic modes) are computed together and time-stepped explicitly. This requires small time steps limited by the acoustic CFL condition (sound speed ~340 m/s).

Use SplitExplicitTimeDiscretization for more efficient time-stepping with larger Δt.

source
Breeze.CompressibleEquations.GaussianRamp — Type
struct GaussianRamp <: AbstractRamp

Gaussian sponge ramp, $\exp[-(z - H)^2 / \text{depth}^2]$, reaching 1 at the lid and $e^{-1}$ one depth below it. Unlike CubicRamp, Sin2Ramp and LinearRamp it is not clamped to zero at the layer base: a weak tail continues all the way down.

That tail is the point: on a long mountain-wave integration a compactly-supported ramp leaves a residual in the far field, worst downstream of the ridge, that a tailed one removes at half the depth. Neither deepening nor strengthening the clamped ramp substitutes — both come out worse downstream, and with a slightly larger core wave, so what they add is reflection rather than absorption. A clamped ramp's relative gradient (1/γ)|∂z γ| is unbounded at its base, and deepening it only moves that base closer to the wave; a Gaussian has no base to reflect off.

What the tail costs is weak damping below the nominal layer. For a steadily forced wave that is not exp(-rate × ramp × t): the response equilibrates against advection, so the amplitude cost scales with rate × ramp(z) / (U k), which on the Schär case is 10% at z = H/2 and 0.07% at H/4. Measured rms w over 0.5 < z < 10 km differs from the clamped ramp by 0.4%. Prefer a clamped ramp when the dynamics just below the sponge must be provably untouched, and this one when a quiet far field matters more.

source
Breeze.CompressibleEquations.LinearRamp — Type
struct LinearRamp <: AbstractRamp

Linear sponge ramp. Cheap but introduces a kink at the bottom of the sponge layer (nonzero slope at $z = H − \text{depth}$), which can cause small partial reflection of upgoing waves in idealised tests. WRF's older damp_opt = 2 form uses this.

source
Breeze.CompressibleEquations.ProportionalSubsteps — Type
struct ProportionalSubsteps <: AcousticSubstepDistribution

Acoustic substep distribution where each WS-RK3 stage independently covers its interval $β_\mathrm{stage} Δt$ with $Nτ = ⌈β_\mathrm{stage} N⌉$ substeps of size $Δτ = β_\mathrm{stage} Δt / Nτ$. The count is proportional to the stage fraction and the size is fitted so the substeps exactly tile each stage — exact coverage at the minimum substep count (no global quantization; Δτ may differ slightly by stage).

This is the default.

source
Breeze.CompressibleEquations.Sin2Ramp — Type
struct Sin2Ramp <: AbstractRamp

$\sin^2$ sponge ramp from Klemp, Dudhia & Hassiotis (2008). Same zero-derivative-at-both-ends behaviour as CubicRamp. Provided for parity with WRF (damp_opt = 3) / MPAS-Atmosphere.

source
Breeze.CompressibleEquations.SplitExplicitTimeDiscretization — Type
struct SplitExplicitTimeDiscretization{N, FT, D, US, AD<:AcousticSubstepDistribution}

Time discretization for fully compressible dynamics that integrates slow terms with a Wicker-Skamarock RK3 outer loop and acoustic terms with split-explicit inner substeps.

The constructor accepts substeps or an acoustic_cfl for choosing the number of acoustic substeps, a forward_weight for off-centering the acoustic solve, an acoustic damping strategy such as ThermalDivergenceDamping, an optional UpperSponge, and a substep_distribution such as ProportionalSubsteps.

Backward integration (time_step!(model, Δt) with Δt < 0) is supported for the linearized acoustic substep loop. See the field-documentation docstring for the A-stability argument, sign-handling of the adaptive substep count, and the irreversibility caveat for the optional UpperSponge.

source
Breeze.CompressibleEquations.ThermalDivergenceDamping — Type
struct ThermalDivergenceDamping{FT, LS} <: AcousticDampingStrategy

Acoustic divergence damping that uses the (ρθ)′ tendency as a discrete proxy for the momentum divergence. From the linearized ρθ-continuity equation $\partial_t (ρθ)' + \nabla\cdot(ρθ^L u') = 0$, the per-substep quantity

\[D \equiv \frac{(ρθ)' - (ρθ)'_\mathrm{old}}{θ^L} \approx -Δτ \, \nabla\cdot(ρu)'\]

is what would otherwise require an extra divergence operator and an extra kernel pass. Building the correction from D reuses the substep's already-resident (ρθ)′ snapshots — that's the algorithmic choice this damping is named for.

Used by Klemp, Skamarock & Ha (2018) / Skamarock & Klemp (1992) / Baldauf (2010). After each acoustic substep, the horizontal momentum perturbation components $(ρu)′$ and $(ρv)′$ pick up an explicit correction proportional to the horizontal gradient of $D$. If damp_vertical = true, the vertical component is folded implicitly into the column tridiag as a Laplacian on the acoustic vertical momentum perturbation: $(ρw)′$ for height-coordinate dynamics and $(ρ ilde{w})′$ for terrain-following dynamics. By default, damp_vertical = false and vertical acoustic damping comes from the off-centered implicit solve.

Per-substep momentum correction (Klemp, Skamarock & Ha 2018 eq. 36, MPAS form):

\[Δ(ρu)′ = -γ · ∂_x D , \quad Δ(ρv)′ = -γ · ∂_y D .\]

with local per-direction horizontal diffusivities. On a uniform square grid this is the finite-difference analogue of MPAS's coef_divdamp = 2·smdiv·config_len_disp/Δτ:

\[γ_x = α \, Δx^2 / Δτ , \qquad γ_y = α \, Δy^2 / Δτ .\]

On anisotropic or latitude-longitude grids, using the local per-direction spacing keeps the nondimensional explicit damping strength approximately uniform across the mesh. Pass length_scale = ℓ to override the automatic local scale with the fixed diffusivity $γ = α ℓ^2 / Δτ$ when a nominal mesh length is more appropriate. The optional vertical tridiag contribution uses $γ_z = α Δz² / Δτ$ when damp_vertical = true.

$α$ is the dimensionless Klemp 2018 coefficient (= MPAS config_smdiv, default 0.1). The combined 2-D horizontal explicit-time stability bound is $8α ≤ 2 → α ≤ 0.25$; the default sits well below it. Combined with the SplitExplicitTimeDiscretization default $\omega = 0.65$, this preserves the exact discrete rest atmosphere at Δt = 20 s and damps divergent acoustic noise in production runs. It should not be read as a guarantee that every grid-scale balanced-mode growth diagnostic is physically correct.

Fields

  • coefficient: Dimensionless damping coefficient $α$ (Klemp 2018 / MPAS config_smdiv). Default 0.1. The horizontal part is explicit and obeys the usual 8α ≤ 2 2-D combined CFL. When damp_vertical = true, the vertical contribution is implicit and is folded into the column tridiag.
  • length_scale: Optional override for the dispersion length $d$. Default nothing (auto: local $γ_x = α Δx^2 / Δτ$ and $γ_y = α Δy^2 / Δτ$). Setting length_scale = ℓ forces a fixed $γ = α \, ℓ² / Δτ$ in both horizontal directions.
  • damp_vertical: If true, the vertical part of the divergence damping is folded into the column tridiag (a Laplacian on (ρw)′ in height coordinates or (ρw̃)′ in terrain-following coordinates). If false (default), no extra vertical damping is applied — the vertical acoustic modes are damped solely by the off-centering of the implicit pressure-gradient solve ($\omega > 0.5$), which Klemp et al. 2018 eq. (32) shows is algebraically equivalent to a vertical divergence damping with diffusivity $γ_z = c² Δτ s/2$ where $s = 2\omega - 1$.
source
Breeze.CompressibleEquations.UpperSponge — Type
struct UpperSponge{FT, R<:AbstractRamp, M, P}

Implicit upper Rayleigh sponge for the substepper. Damps the vertical momentum toward zero inside a layer of thickness depth below the model lid, with peak damping rate damping_rate (in 1/s) at the lid scaled by ramp(z).

The damping acts on the total momentum, which the substep loop carries as $ρw = ρw^L + (ρw)′$, so it is applied in two matching pieces:

  • the stage-entry part $-\text{rate} × \text{ramp}(z) × ρw^L$ is a known constant across the substeps and enters the slow tendency $G^s_{ρw}$. This half targets the Cartesian $ρw$ on every grid, height-coordinate and terrain-following alike, because a horizontally uniform wind over sloping coordinate surfaces has $ρw = 0$ but $ρ\tilde{w} = -\text{slope} · ρu$, so damping $ρ\tilde{w}^L$ would drive the mean flow to follow the coordinate surfaces;
  • the acoustic perturbation part is CN-weighted inside the column tridiag (paralleling the implicit divergence damping): $δτᵐ⁺ × \text{rate} × \text{ramp}(z)$ on the LHS diagonal, $δτˢ⁻ × \text{rate} × \text{ramp}(z)$ on the explicit-half RHS. This half acts on whichever vertical-momentum perturbation the substep evolves, $(ρw)′$ in height coordinates and $(ρ\tilde{w})′$ in terrain-following coordinates. Either way it needs no Cartesian correction, since the mean-flow offset lives entirely in the stage-entry state.

Damping $(ρw)′$ alone would not absorb anything: the perturbation measures the change over an RK stage, so a quasi-steady gravity wave passes through untouched. This split matches the Rayleigh-layer form of the Klemp, Dudhia & Hassiotis (2008) absorbing treatment used in WRF (damp_opt=3) and MPAS-Atmosphere. The profile shape is controlled by ramp; use Sin2Ramp for the classic $\sin^2$ profile.

Keyword arguments

  • damping_rate: peak damping rate at the lid, in 1/s. Default 0.2.

    Because the damping is fully implicit in the inner-loop tridiag, it is unconditionally stable for any positive value, so the choice is guided by physics rather than CFL. Typical guidance:

    • $\text{rate} ≳ N$ (Brunt–Väisälä frequency, ~0.01 /s in the stratosphere) is the lower bound at which gravity waves are absorbed rather than reflected within the layer crossing time.
    • WRF's dampcoef default and Klemp et al.'s recommendation is 0.2 (i.e. τ ≈ 5 s at the lid) — comfortably above $N$ and aggressive enough to absorb in one or two crossings.
    • Larger values are fine numerically but produce a sharper "cap" near the lid; if the application cares about resolved dynamics just below the sponge, prefer $\text{rate} ≈ 0.1$ and a deeper layer.
  • depth: sponge-layer thickness below the lid, in metres along the reference vertical coordinate. Default 5e3.

    Should span at least ~10 grid cells in the vertical to give the smooth profile room to absorb without aliasing; for $Δz ≈ 1\,\text{km}$ the default of 5 km gives 5 cells (marginal — bump to 10 km if w-spectrum has structure right below the lid).

  • ramp: an AbstractRamp controlling the profile shape. Default CubicRamp(). Other built-ins: Sin2Ramp(), GaussianRamp(), LinearRamp(). Custom shapes are supported by subtyping AbstractRamp and defining (::MyRamp)(z, sponge_top, depth).

  • mask: optional extra damping region, a function mask(x, y, z) of the face node coordinates (λ, φ, z on a LatitudeLongitudeGrid) returning a value in $[0, 1]$. The damping rate becomes $γ = \text{rate} × \max(\text{ramp}(z), \text{mask}(x, y, z))$, so the same implicit Rayleigh treatment covers, for example, the lateral relaxation zone of a nested limited-area model. Default nothing (lid layer only). Because the damping is implicit, it removes the rate × Δt ≲ 2.5 stability limit that an explicit Relaxation forcing on ρw imposes on the outer time step.

Without a mask, the ramp depends only on the reference vertical coordinate (no horizontal variation), so the sponge does not break zonal symmetry and remains uniform over terrain-following grids. That is also what makes the damping rate $γ(z) = \text{rate} × \text{ramp}(z)$ a 1D profile over z-faces: UpperSponge(; ...) is a lightweight skeleton with damping_profile = nothing, and materialize_sponge evaluates ramp once per face at AcousticSubstepper construction and stores the result. The substep kernels then read γ with a single load instead of re-evaluating the shape twice per face per acoustic substep.

source
Breeze.CompressibleEquations.WickerSkamarock3 — Type
struct WickerSkamarock3 <: AcousticOuterScheme

Three-stage Wicker–Skamarock RK3 outer scheme (Wicker and Skamarock 2002) with canonical stage fractions $β = (1/3, 1/2, 1)$. Each stage resets the prognostic state to $U^n$ and applies a fraction $β_k Δt$ of the slow tendency evaluated at the previous-stage state, while the acoustic substep loop advances linearized perturbations about each RK stage-entry state.

source
Breeze.CompressibleEquations.acoustic_rk3_substep_loop! — Function
acoustic_rk3_substep_loop!(
    model::AtmosphereModel,
    substepper,
    Δt,
    β_stage,
    Uᴸ,
    advection=nothing;
    rounding=RoundToNearest()
)

Execute one Wicker–Skamarock RK3 stage of the linearized acoustic substep loop. Number and size of substeps in this stage depend on substepper.substep_distribution. The recovery of the full state from the stage-entry state and the accumulated perturbations is rounded with the round-off treatment rounding.

source
Breeze.CompressibleEquations.compute_transport_density_tendency! — Method
compute_transport_density_tendency!(
    substepper::AcousticSubstepper,
    model,
    velocities
)

Compute the dry air's share, ρᵈ / ρ, of the divergence of the mass flux ρ 𝐮 that the moisture tendencies were built with, where velocities are their transport velocities: the dry density tendency that the dilution part of the moisture content ramps with (Section 3b). Call this whenever the moisture tendencies are built, with the velocities they were built with.

source
Breeze.CompressibleEquations.freeze_linearization_state! — Method
freeze_linearization_state!(
    substepper::AcousticSubstepper,
    model
)

Compute the background quantities used by the substepper as the first linearization point of an outer step. Subsequent RK stages call prepare_acoustic_cache!, which refreshes the same cached quantities to the stage-entry state.

After this call:

  • linearization_potential_temperature = θᴸ = ρθᴸ/ρᴸ derived from model.dynamics.dry_density + ρθ
  • linearization_pressure_coefficient = Cᴸ, the slope ∂p/∂(ρθ) of the equation of state at that state (see refresh_linearization_basic_state!)
source
Breeze.CompressibleEquations.prepare_acoustic_cache! — Method
prepare_acoustic_cache!(
    substepper::AcousticSubstepper,
    model
)

Stage-start cache preparation. Refreshes the cached linearization quantities (θᴸ, Cᴸ) to the stage-entry state $Uᴸ_\mathrm{stage}$ (per Skamarock & Klemp 2008 above eq. 16), recomputing them from the live model.dynamics.*. The rewind-perturbation initialization (initialize_stage_perturbations!, called next) handles the WS-RK3 invariant by setting $(ρ)′_\mathrm{init} = Uᴸ_\mathrm{outer} − Uᴸ_\mathrm{stage}$ (zero for stage 1; nonzero for stages 2 and 3).

source

Forcings

Breeze.Forcings.SpecificForcing — Method
SpecificForcing(
    forcing
) -> SpecificForcing{<:Any, Nothing, Nothing}

Wrap a user-supplied forcing that produces a specific (per-unit-mass) tendency so that Breeze applies the density multiply $ρ$ at kernel time. After materialization, the kernel callable returns

\[ρ(i, j, k) \, F_ϕ(i, j, k, t)\]

interpolating $ρ$ to the appropriate cell face for fields whose target prognostic lives at Face in any direction (e.g. $ρ$ is interpolated to x-Face for u-forcings via $ℑxᶠᵃᵃ$, to z-Face for w via $ℑzᵃᵃᶠ$). Under AnelasticDynamics, ρ is the reference density ρᵣ(z). Under CompressibleDynamics, the weighting density depends on the target conservation law: momentum and thermodynamic tendencies use the dry-air continuity density ρᵈ, while moisture, microphysical moments, and user tracers use total density ρ. The same wrapper handles every weighting density.

Users typically supply specific forcings directly through specific-named keys (u, v, w, θ, s, qᵉ, qᵛ, …) in the forcing NamedTuple passed to AtmosphereModel, and the dispatch wraps each entry in SpecificForcing automatically. The wrapper can also be constructed directly when finer control is needed.

The inner forcing can be anything accepted by Breeze's materialize_atmosphere_model_forcing: a function (x, y, z, t), a Returns callable, a Field, an Oceananigans.Forcing, a Breeze forcing such as SubsidenceForcing or one produced by geostrophic_forcings, or a tuple of these.

source
Breeze.Forcings.SubsidenceForcing — Method
SubsidenceForcing(
    wˢ;
    advection=UpwindBiased(order = 1)
) -> SubsidenceForcing{<:Any, Nothing, S, Nothing} where S<:(UpwindBiased{N, FT, Oceananigans.Utils.ExplicitTimeDiscretization} where {N, FT})

Forcing that represents large-scale subsidence advecting horizontally-averaged fields downward. The kernel returns the specific tendency

\[F_ϕ = - w^s \, ∂_z \overline{ϕ}\]

where $w^s$ is the subsidence_vertical_velocity and $\overline{ϕ}$ is the horizontal average of the field being forced. Supply SubsidenceForcing under the specific prognostic name (e.g. θ, qᵉ, u); the AtmosphereModel dispatch wraps it in SpecificForcing so the density factor $ρ$ is applied automatically at kernel time.

Arguments

  • wˢ: Either a function of z specifying the subsidence velocity profile, or a Field containing the subsidence velocity.

Keyword arguments

  • advection: the discretization of $w^s ∂_z \overline{ϕ}$. The default UpwindBiased(order = 1) damps $2Δz$ modes and does not undershoot at sharp gradients. Centered() cannot see a $2Δz$ mode, so it persists; higher-order upwind schemes damp it but may over- or undershoot.

With an upwind scheme every cell, including the two boundary cells, is updated from its own face fluxes. Air leaving the column through a boundary face carries the boundary cell's value. Air entering it carries the value extrapolated linearly from the two cells inside, so a linear profile crosses the boundary undistorted; for mass fractions such as moisture that value is bounded below by zero, so subsidence never brings negative moisture into the column.

The horizontal average is computed automatically during update_state!.

Example

using Breezegrid = RectilinearGrid(size=(64, 64, 75), x=(0, 6400), y=(0, 6400), z=(0, 3000))wˢ(z) = z < 1500 ? -0.0065 * z / 1500 : -0.0065 * (1 - (z - 1500) / 600)subsidence = SubsidenceForcing(wˢ)forcing = (; θ=subsidence, qᵛ=subsidence)model = AtmosphereModel(grid; forcing)model.forcing.ρθ.forcing# outputSubsidenceForcing with wˢ: 1×1×76 Field{Nothing, Nothing, Face} reduced over dims = (1, 2) on RectilinearGrid on CPU├── averaged_field: 1×1×75 Field{Nothing, Nothing, Center} reduced over dims = (1, 2) on RectilinearGrid on CPU└── advection: UpwindBiased(order=1)
source
Breeze.Forcings.TemperatureForcing — Method
TemperatureForcing(
    temperature_tendency
) -> TemperatureForcing{<:Any, Nothing, Nothing, Nothing, Nothing, Nothing}

Forcing by a prescribed temperature tendency $∂ₜT$ (K s⁻¹), such as the large-scale heating of a single-column case. Supply it under the specific energy key E, as in forcing = (; E = TemperatureForcing(∂ₜT)). ∂ₜT can be anything accepted as a forcing: a Field, a function, a Returns, an Oceananigans.Forcing. At kernel time it is converted to an energy tendency with the local mixture heat capacity,

\[F_E = cᵖᵐ ∂ₜT ,\]

where $cᵖᵐ$ is evaluated from the moisture mass fractions the tendency kernels see (vapor, liquid and ice from the microphysics scheme). Breeze then multiplies by the density and routes the result onto the thermodynamic variable: LiquidIcePotentialTemperatureFormulation divides an energy tendency by $cᵖᵐ Π$, so $θ$ changes at $∂ₜT / Π$, the rate at which $T = Π θ + (ℒˡᵣ qˡ + ℒⁱᵣ qⁱ) / cᵖᵐ$ changes at fixed moisture and pressure by $∂ₜT$. StaticEnergyFormulation adds it to $ρs$ unconverted, and $s = cᵖᵐ T + g z - ℒˡᵣ qˡ - ℒⁱᵣ qⁱ$ changes by $cᵖᵐ ∂ₜT$.

Converting with the dry heat capacity $cᵖᵈ$ instead, as in E = cᵖᵈ * ∂ₜT, heats humid air too little by the factor $cᵖᵈ / cᵖᵐ$: about 1.7% at 20 g kg⁻¹ of vapor.

using Breezegrid = RectilinearGrid(size=4, z=(0, 1000), topology=(Flat, Flat, Bounded))cooling(z, t) = -2 / 86400 # radiative cooling, K s⁻¹forcing = TemperatureForcing(cooling)model = AtmosphereModel(grid; forcing=(; E=forcing))forcing# outputTemperatureForcing with temperature_tendency: cooling (generic function with 1 method)
source
Breeze.Forcings.geostrophic_forcings — Method
geostrophic_forcings(uᵍ, vᵍ)

Create a pair of geostrophic forcings for the x- and y-momentum equations, keyed under specific names u and v. Each GeostrophicForcing returns a specific tendency; the model's density factor ρ is applied automatically via SpecificForcing when the forcing is dispatched under a specific key, with the correct horizontal interpolation of ρ to the appropriate cell face.

The Coriolis parameter is extracted from the model's coriolis during model construction.

Arguments

  • uᵍ: Function of z specifying the x-component of the geostrophic velocity.
  • vᵍ: Function of z specifying the y-component of the geostrophic velocity.

Returns a NamedTuple with u and v forcing entries that can be merged into the model forcing.

Example

using Breezeuᵍ(z) = -10 + 0.001zvᵍ(z) = 0.0coriolis = FPlane(f=1e-4)forcing = geostrophic_forcings(uᵍ, vᵍ)# outputNamedTuple with 2 GeostrophicForcings:├── u: GeostrophicForcing{XDirection}│   └── geostrophic_velocity: vᵍ (generic function with 1 method)└── v: GeostrophicForcing{YDirection}    └── geostrophic_velocity: uᵍ (generic function with 1 method)
source

KinematicDriver

Breeze.KinematicDriver — Module
KinematicDriver

Module implementing kinematic dynamics for atmosphere models.

Kinematic dynamics prescribes the velocity field rather than solving for it, enabling isolated testing of microphysics, thermodynamics, and other physics without the complexity of solving the momentum equations.

This is analogous to the kin1d driver in P3-microphysics.

source
Breeze.KinematicDriver.PrescribedDensity — Type
PrescribedDensity{D}(density) where D -> PrescribedDensity
PrescribedDensity(density::D) where D -> PrescribedDensity

Wrapper indicating that density is fixed (not prognostic).

source
Breeze.KinematicDriver.PrescribedDynamics — Type
struct PrescribedDynamics{Div, D, P, SP, FT}

Dynamics for kinematic atmosphere models where velocity is prescribed. The type parameter Div indicates whether divergence correction is applied.

source
Breeze.KinematicDriver.PrescribedDynamics — Method
PrescribedDynamics(
    density;
    pressure=nothing,
    surface_pressure=nothing,
    base_pressure=101325,
    standard_pressure=100000.0,
    divergence_correction=false
) -> PrescribedDynamics{<:Any, <:Any, Nothing, Nothing}

Construct PrescribedDynamics from a density field or PrescribedDensity. If pressure=nothing, hydrostatic pressure is computed during materialization. base_pressure is the pressure datum at z = 0. On a raised domain, the default bottom-face pressure extends the lowest prescribed density down to the datum; pass surface_pressure to prescribe a different hydrostatic anchor explicitly.

source
Breeze.KinematicDriver.PrescribedDynamics — Method
PrescribedDynamics(
    reference_state::ReferenceState;
    divergence_correction=false
) -> PrescribedDynamics{<:Any, D} where D<:PrescribedDensity

Construct PrescribedDynamics from a ReferenceState. Wraps density in PrescribedDensity (fixed in time).

If divergence_correction=true, scalar tendencies include +c∇·(ρU) to account for the non-divergent velocity field.

Example

The grid's bottom face is the ground, so give it as z = (0, Lz); on a domain that starts at $z = 0$ the bottom-face surface_pressure and the $z = 0$ base_pressure datum coincide.

using Oceananigansusing Breezegrid = RectilinearGrid(size=(4, 4, 8), x=(0, 1000), y=(0, 1000), z=(0, 2000))reference_state = ReferenceState(grid, ThermodynamicConstants())dynamics = PrescribedDynamics(reference_state)(dynamics.surface_pressure[1, 1, 1], dynamics.base_pressure)# output(101325.0, 101325.0)
source

Microphysics

Breeze.Microphysics.BulkMicrophysics — Type
BulkMicrophysics(
    FT::DataType=Oceananigans.defaults.FloatType;
    categories=nothing,
    cloud_formation=SaturationAdjustment(FT),
    precipitation_boundary_condition=nothing,
    negative_moisture_correction=nothing
) -> BulkMicrophysics{N, Nothing, Nothing, Nothing} where N<:(SaturationAdjustment{E, S} where {E<:MixedPhaseEquilibrium, S<:SecantSolver})

Return a BulkMicrophysics microphysics scheme.

Keyword arguments

  • categories: Microphysical categories (e.g., cloud liquid, cloud ice, rain, snow) or nothing for non-precipitating
  • cloud_formation: Cloud formation scheme (default: SaturationAdjustment)
  • precipitation_boundary_condition: Bottom boundary condition for precipitation sedimentation.
    • nothing (default): Precipitation passes through the bottom
    • ImpenetrableBoundaryCondition(): Precipitation collects at the bottom
  • negative_moisture_correction: Correction scheme for negative moisture produced by advection.
    • nothing (default): No correction
      • VerticalBorrowing(): Vertical redistribution of the moisture prognostic only
    • SpeciesBorrowing(): Same-level species borrowing only
    • SpeciesBorrowing(vertical_borrowing=VerticalBorrowing()): Species borrowing with vertical redistribution
source
Breeze.Microphysics.BulkMicrophysics — Type
struct BulkMicrophysics{N, C, B, NMC}

Bulk microphysics scheme with cloud formation and precipitation categories.

Fields

  • cloud_formation: Cloud formation scheme (saturation adjustment or non-equilibrium)
  • categories: Precipitation categories (e.g., rain, snow) or nothing
  • precipitation_boundary_condition: Bottom boundary condition for precipitation sedimentation.
    • nothing (default): Precipitation passes through the bottom (open boundary)
    • ImpenetrableBoundaryCondition(): Precipitation collects at the bottom (zero terminal velocity at surface)
  • negative_moisture_correction: Correction scheme for negative moisture produced by advection.
    • nothing (default): No correction
      • VerticalBorrowing(): Vertical redistribution of the moisture prognostic only
    • SpeciesBorrowing(): Same-level species borrowing only
    • SpeciesBorrowing(vertical_borrowing=VerticalBorrowing()): Species borrowing with vertical redistribution
source
Breeze.Microphysics.ConstantRateCondensateFormation — Type
struct ConstantRateCondensateFormation{FT} <: Breeze.Microphysics.AbstractCondensateFormation

Return a condensate formation model that applies a constant phase-change rate.

This type is intended to be usable for both liquid (condensation/evaporation) and ice (deposition/sublimation).

source
Breeze.Microphysics.DCMIP2016KesslerMicrophysics — Type
DCMIP2016KesslerMicrophysics(
    FT=Oceananigans.defaults.FloatType;
    dcmip_temperature_scale=237.3,
    terminal_velocity_coefficient=36.34,
    density_scale=0.001,
    terminal_velocity_exponent=0.1364,
    autoconversion_rate=0.001,
    autoconversion_threshold=0.001,
    accretion_rate=2.2,
    accretion_exponent=0.875,
    evaporation_ventilation_coefficient_1=1.6,
    evaporation_ventilation_coefficient_2=124.9,
    evaporation_ventilation_exponent_1=0.2046,
    evaporation_ventilation_exponent_2=0.525,
    diffusivity_coefficient=2.55e8,
    thermal_conductivity_coefficient=540000.0,
    substep_cfl=0.8,
    maximum_sedimentation_substeps=0
) -> Breeze.Microphysics.DCMIP2016KesslerMicrophysics

Construct a DCMIP2016 implementation of the Kessler (1969) warm-rain bulk microphysics scheme.

This implementation follows the DCMIP2016 test case specification, which is based on Klemp and Wilhelmson (1978).

Positional Arguments

  • FT: Floating-point type for all parameters (default: Oceananigans.defaults.FloatType).

References

  • Zarzycki, C. M., et al. (2019). DCMIP2016: the splitting supercell test case. Geoscientific Model Development, 12, 879–892.
  • Kessler, E. (1969). On the Distribution and Continuity of Water Substance in Atmospheric Circulations. Meteorological Monographs, 10(32).
  • Klemp, J. B., & Wilhelmson, R. B. (1978). The simulation of three-dimensional convective storm dynamics. Journal of the Atmospheric Sciences, 35(6), 1070-1096.
  • DCMIP2016 Fortran implementation (kessler.f90 in DOI: 10.5281/zenodo.1298671)

Moisture Categories

This scheme represents moisture in three categories:

  • Water vapor mixing ratio (rᵛ)
  • Cloud water mixing ratio (rᶜˡ)
  • Rain water mixing ratio (rʳ)

Breeze tracks moisture using mass fractions (q), whereas the Kessler scheme uses mixing ratios (r). Conversions between these representations are performed internally. In Breeze, water vapor is not a prognostic variable; instead, it is diagnosed from the total specific moisture qᵗ and the liquid condensates.

Physical Processes

  1. Autoconversion: Cloud water converts to rain water when the cloud water mixing ratio exceeds a threshold.
  2. Accretion: Rain water collects cloud water as it falls.
  3. Saturation Adjustment: Water vapor condenses to cloud water or cloud water evaporates to maintain saturation.
  4. Rain Evaporation: Rain water evaporates into subsaturated air.
  5. Rain Sedimentation: Rain water falls gravitationally.

Implementation Details

  • The microphysics update is applied via a GPU-compatible kernel launched from microphysics_model_update!.
  • Rain sedimentation uses subcycling to satisfy CFL constraints, following the Fortran implementation.
  • All microphysical updates are applied directly to the state variables in the kernel.

Keyword Arguments

Saturation (Tetens/Clausius-Clapeyron formula)

  • dcmip_temperature_scale (T_DCMIP2016): A parameter of uncertain provenance that appears in the DCMIP2016 implementation of the Kessler scheme (line 105 of kessler.f90 in DOI: 10.5281/zenodo.1298671)

The "saturation adjustment coefficient" f₅ is then computed as

\[f₅ = a T_DCMIP2016 ℒˡᵣ / cᵖᵈ\]

where a is the liquid_coefficient for Tetens' saturation vapor pressure formula, ℒˡᵣ is the latent heat of vaporization of liquid water, and cᵖᵈ is the heat capacity of dry air.

Rain Terminal Velocity (Klemp & Wilhelmson 1978, eq. 2.15)

Terminal velocity: 𝕎ʳ = a𝕎 × (ρ × rʳ × Cᵨ)^β𝕎 × √(ρ₀/ρ)

  • terminal_velocity_coefficient (a𝕎): Terminal velocity coefficient in m/s (default: 36.34)
  • density_scale (Cᵨ): Density scale factor for unit conversion (default: 0.001)
  • terminal_velocity_exponent (β𝕎): Terminal velocity exponent (default: 0.1364)
  • ρ: Density
  • ρ₀: Reference density at z=0

Autoconversion

  • autoconversion_rate (k₁): Autoconversion rate coefficient in s⁻¹ (default: 0.001)
  • autoconversion_threshold (rᶜˡ★): Critical cloud water mixing ratio threshold in kg/kg (default: 0.001)

Accretion

  • accretion_rate (k₂): Accretion rate coefficient in s⁻¹ (default: 2.2)
  • accretion_exponent (βᵃᶜᶜ): Accretion exponent for rain mixing ratio (default: 0.875)

Rain Evaporation (Klemp & Wilhelmson 1978, eq. 2.14)

Ventilation: (Cᵉᵛ₁ + Cᵉᵛ₂ × (ρ rʳ)^βᵉᵛ₁) × (ρ rʳ)^βᵉᵛ₂

  • evaporation_ventilation_coefficient_1 (Cᵉᵛ₁): Evaporation ventilation coefficient 1 (default: 1.6)
  • evaporation_ventilation_coefficient_2 (Cᵉᵛ₂): Evaporation ventilation coefficient 2 (default: 124.9)
  • evaporation_ventilation_exponent_1 (βᵉᵛ₁): Evaporation ventilation exponent 1 (default: 0.2046)
  • evaporation_ventilation_exponent_2 (βᵉᵛ₂): Evaporation ventilation exponent 2 (default: 0.525)
  • diffusivity_coefficient (Cᵈⁱᶠᶠ): Diffusivity-related denominator coefficient (default: 2.55e8)
  • thermal_conductivity_coefficient (Cᵗʰᵉʳᵐ): Thermal conductivity-related denominator coefficient (default: 5.4e5)

Numerical

  • substep_cfl: CFL safety factor for sedimentation subcycling (default: 0.8)
  • maximum_sedimentation_substeps: Static bound on the number of sedimentation substeps, for architectures whose kernels cannot loop a data-dependent number of times (Reactant reverse mode; required there, see sedimentation_substep_limit). A step that needs more substeps is not truncated: its update is NaN. Choose it from eager control runs, in which microphysical_fields.sedimentation_substeps records the most substeps each column has needed. Ignored by eager architectures (default: 0, no bound).
source
Breeze.Microphysics.InstantaneousPrecipitation — Type
InstantaneousPrecipitation(
    FT::DataType=Oceananigans.defaults.FloatType;
    equilibrium=WarmPhaseEquilibrium(),
    solver=SecantSolver(FT)
) -> InstantaneousPrecipitation{S} where S<:(SaturationAdjustment{WarmPhaseEquilibrium, S} where S<:SecantSolver)

Construct an InstantaneousPrecipitation scheme. equilibrium selects the phase equilibrium used by the underlying saturation solve (default warm-phase), and solver controls its iteration (see SaturationAdjustment).

source
Breeze.Microphysics.InstantaneousPrecipitation — Type
struct InstantaneousPrecipitation{S}

Instantaneous-precipitation microphysics: an instantaneous, irreversible condensation with immediate rain-out and no re-evaporation (no cloud or rain stage). Excess water vapor above saturation condenses, releases its latent heat to the air, and is removed as precipitation in the same step. This is the "large-scale condensation" of the DCMIP2016 Reed–Jablonowski simple-physics suite.

The saturation/latent-heat solve is delegated to a SaturationAdjustment instance (saturation_adjustment), so the equilibrium thermodynamics are shared and validated. The distinction is irreversibility: the condensate is purged from the prognostic vapor every step and cannot re-evaporate.

The prognostic moisture is the vapor density ρqᵛ (no condensate is retained). On the compressible core, rain-out leaves dry-air density unchanged and reduces total density by the removed condensate. The remaining vapor mass fraction and potential temperature are recomputed at that density, preserving the temperature reached during condensation.

source
Breeze.Microphysics.NonEquilibriumCloudFormation — Type
NonEquilibriumCloudFormation(liquid, ice=nothing)

A cloud formation scheme where cloud liquid and ice are prognostic variables that evolve via condensation/evaporation and deposition/sublimation tendencies, rather than being diagnosed instantaneously via saturation adjustment.

The condensation/evaporation and deposition/sublimation tendencies are commonly modeled as relaxation toward saturation with timescale τ_relax, including a latent-heat (psychrometric/thermal) correction factor; see Morrison and Grabowski (2008), Appendix Eq. (A3), and standard cloud microphysics texts such as Pruppacher and Klett (2010) or Rogers and Yau (1989).

For some bulk schemes (e.g. the CloudMicrophysics 1M extension), liquid and ice may be set to nothing and used purely as phase indicators (warm-phase vs mixed-phase), with any relaxation timescales sourced from the scheme's precipitation/category parameters instead.

Fields

  • liquid: Parameters for cloud liquid (contains relaxation timescale τ_relax)
  • ice: Parameters for cloud ice (contains relaxation timescale τ_relax), or nothing for warm-phase only

References

  • Morrison, H. and Grabowski, W. W. (2008). A novel approach for representing ice microphysics in models: Description and tests using a kinematic framework. J. Atmos. Sci., 65, 1528–1548. https://doi.org/10.1175/2007JAS2491.1
  • Pruppacher, H. R. and Klett, J. D. (2010). Microphysics of Clouds and Precipitation (2nd ed.).
  • Rogers, R. R. and Yau, M. K. (1989). A Short Course in Cloud Physics (3rd ed.).
source
Breeze.Microphysics.SaturationAdjustment — Type
SaturationAdjustment(
    FT::DataType=Oceananigans.defaults.FloatType;
    solver=SecantSolver(FT; abstol = 0.0001, maxiter = 20),
    equilibrium=MixedPhaseEquilibrium(FT),
    tolerance=nothing,
    maxiter=nothing
) -> SaturationAdjustment{E, S} where {E<:MixedPhaseEquilibrium, S<:SecantSolver}

Return SaturationAdjustment microphysics representing an instantaneous adjustment to equilibrium between condensates and water vapor, computed by a secant iteration on the temperature residual controlled by solver.

The options for equilibrium are:

  • WarmPhaseEquilibrium() representing an equilibrium between water vapor and liquid water.

  • MixedPhaseEquilibrium() representing a temperature-dependent equilibrium between water vapor, possibly supercooled liquid water, and ice. The equilibrium state is modeled as a linear variation of the equilibrium liquid fraction with temperature, between the freezing temperature (e.g. 273.15 K) below which liquid water is supercooled, and the temperature of homogeneous ice nucleation temperature (e.g. 233.15 K) at which the supercooled liquid fraction vanishes.

The options for solver are SecantSolver (default: SecantSolver(abstol=1e-4, maxiter=20), an absolute tolerance on the temperature-like residual in Kelvin, floored at the residual's rounding noise, about 1e-3 K in Float32) and FixedIterations, which performs a fixed number of secant steps with no convergence test (the form required for Reactant tracing and cheap reverse-mode differentiation).

source
Breeze.Microphysics.RelativeHumidity — Method
RelativeHumidity(
    model
) -> KernelFunctionOperation{<:Any, <:Any, <:Any, <:Any, T, K, D} where {T, K<:Breeze.Microphysics.RelativeHumidityKernelFunction, D<:Tuple}

Return a KernelFunctionOperation representing the relative humidity $ℋ$, defined as the ratio of vapor pressure to saturation vapor pressure:

\[ℋ = \frac{pᵛ}{pᵛ⁺}\]

where $pᵛ$ is the vapor pressure (partial pressure of water vapor) computed from the ideal gas law

\[pᵛ = ρ qᵛ Rᵛ T\]

and $pᵛ⁺$ is the saturation vapor pressure.

For unsaturated conditions, $ℋ < 1$. For saturated conditions with saturation adjustment microphysics, $ℋ = 1$ (or very close to it due to numerical precision).

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 128), extent=(1e3, 1e3, 1e3))microphysics = SaturationAdjustment()model = AtmosphereModel(grid; microphysics)set!(model, θ=300, qᵗ=0.005)  # subsaturatedℋ = RelativeHumidity(model)# outputKernelFunctionOperation at (Center, Center, Center)├── grid: 1×1×128 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── kernel_function: RelativeHumidityKernelFunction└── arguments: ()

As with other diagnostics, RelativeHumidity may be wrapped in Field to store the result:

ℋ_field = RelativeHumidity(model) |> Field# output1×1×128 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×128 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×134 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:131) with eltype Float64 with indices 0:2×0:2×-2:131    └── max=0.214949, min=0.137169, mean=0.172626

We also provide a convenience constructor for the Field:

ℋ_field = RelativeHumidityField(model)# output1×1×128 Field{Center, Center, Center} on RectilinearGrid on CPU├── grid: 1×1×128 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── boundary conditions: FieldBoundaryConditions│   └── west: Periodic, east: Periodic, south: Periodic, north: Periodic, bottom: ZeroFlux, top: ZeroFlux, immersed: Nothing├── operand: KernelFunctionOperation at (Center, Center, Center)├── status: time=0.0└── data: 3×3×134 StaticStridesOffsetArray(::Array{Float64, 3}, 0:2, 0:2, -2:131) with eltype Float64 with indices 0:2×0:2×-2:131    └── max=0.214949, min=0.137169, mean=0.172626
source
Breeze.Microphysics.Supersaturation — Method
Supersaturation(
    model
) -> Oceananigans.AbstractOperations.BinaryOperation{LX, LY, LZ, typeof(-), A, Int64} where {LX, LY, LZ, A}

Return an AbstractOperation representing the supersaturation with respect to liquid water,

\[𝒮 = ℋ - 1 = \frac{pᵛ}{pᵛ⁺} - 1\]

computed from RelativeHumidity. Air with $𝒮 > 0$ grows cloud droplets by condensation and, above a droplet's critical supersaturation, activates it; air with $𝒮 < 0$ evaporates them. Because the supersaturation in a cloud is a small residual of two much larger numbers, it is the natural diagnostic to output rather than the humidity itself.

Examples

using Breezegrid = RectilinearGrid(size=(1, 1, 128), extent=(1e3, 1e3, 1e3))model = AtmosphereModel(grid; microphysics=SaturationAdjustment())set!(model, θ=300, qᵗ=0.005)  # subsaturated𝒮 = Supersaturation(model)# outputBinaryOperation at (Center, Center, Center)├── grid: 1×1×128 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo└── tree:    - at (Center, Center, Center)    ├── KernelFunctionOperation at (Center, Center, Center)    └── 1

The convenience constructor returns the Field instead:

𝒮_field = SupersaturationField(model)maximum(𝒮_field) < 0   # the sounding is subsaturated everywhere# outputtrue
source
Breeze.Microphysics.adjust_thermodynamic_state — Function
adjust_thermodynamic_state(
    𝒰₀::Breeze.Thermodynamics.AbstractThermodynamicState,
    microphysics::SaturationAdjustment,
    constants,
    precipitation=(0, 0)
) -> Breeze.Thermodynamics.AbstractThermodynamicState

Return the saturation-adjusted thermodynamic state using a secant iteration.

The state selects the constraint: fixed pressure for reference-pressure states, or fixed density with pressure p = ρ Rᵐ T for LiquidIceDensityState. The conserved thermodynamic variable, initial temperature guesses, and solver are retained in either case. The residual uses the state's selected temperature inversion, including non-iterated and fixed-iteration inversions, so equilibrium is evaluated at the returned temperature.

precipitation = (qʳ, qˢⁿ) specifies fixed rain and snow mass fractions, included in the state's total water, heat capacity, gas constant, and latent energy.

source
Breeze.Microphysics.kessler_terminal_velocity — Method
kessler_terminal_velocity(rʳ, ρ, ρ₁, microphysics)

Compute rain terminal velocity (m/s) following Klemp and Wilhelmson (1978) eq. 2.15.

The terminal velocity is computed as:

\[𝕎ʳ = a^𝕎 (ρ rʳ Cᵨ)^{β^𝕎} \sqrt{ρ₀/ρ}\]

where $a^𝕎$ is the terminal_velocity_coefficient, $Cᵨ$ is the density_scale, and $β^𝕎$ is the terminal_velocity_exponent.

source
Breeze.Microphysics.number_concentration — Method
number_concentration(model, species::Symbol)

Lazy diagnostic returning the total number concentration $ρnˣ$ (m⁻³) for the requested species.

For OneMomentCloudMicrophysics, species ∈ (:rain, :snow) returns a KernelFunctionOperation that computes $n_0 \, λ^{-1}$ from the prognostic $ρqˣ$ and the scheme's size distribution. Snow's intercept $n_0$ depends on $(q, ρ)$ per Kaul et al. (2015) — so this diagnostic stays consistent with the scheme's actual DSD without re-encoding species-specific physics at every call site.

For TwoMomentCloudMicrophysics, returns the prognostic $ρnˣ$ field directly (e.g., :rain → ρnʳ, :cloud_liquid → ρnᶜˡ).

For PredictedParticlePropertiesMicrophysics, returns the prognostic $ρnˣ$ field when present. In the default prescribed-cloud-number configuration, :cloud_liquid returns a lazy constant operation based on the configured droplet number.

Returns nothing if the species is not carried by the model (e.g., :hail for a 1-mom scheme without hail). Errors for microphysics schemes that do not define a DSD-based number concentration (e.g., SaturationAdjustment).

The return shape is therefore polymorphic: a lazy KernelFunctionOperation for diagnosed or prescribed concentrations and a stored Field for prognostic concentrations. Use number_concentration_field when you want a uniformly Field-typed handle.

source
Breeze.Microphysics.number_concentration_field — Method
number_concentration_field(model, species::Symbol)

Field-typed handle for the number_concentration diagnostic. Allocates a Field shell around lazy KernelFunctionOperations (use compute! to populate it) and returns prognostic $ρnˣ$ fields directly. Returns nothing when the requested species is not carried by the model.

source

Microphysics.PredictedParticleProperties

Breeze.Microphysics.PredictedParticleProperties — Module
PredictedParticleProperties

Predicted Particle Properties (P3) microphysics scheme implementation.

P3 is a bulk microphysics scheme that uses a single ice category with continuously predicted properties (rime fraction, rime density, liquid fraction) rather than multiple discrete ice categories.

Key Features

  • Single ice category with predicted properties
  • Two-moment ice (mass and number)
  • Predicted liquid fraction on ice particles
  • Rime fraction and rime density evolution
  • Ice-side integrals are read from the ASCII lookup tables; rain 1D integrals are tabulated at startup using Chebyshev–Gauss quadrature

Complete Reference List

This implementation is based on the following P3 papers:

  1. Morrison & Milbrandt (2015a) - Original P3: $m(D)$, $A(D)$, $\mathbb{W}(D)$, process rates Morrison and Milbrandt (2015a)

  2. Morrison et al. (2015b) - Part II: Case study validation Morrison et al. (2015b)

  3. Milbrandt & Morrison (2016) - Part III: Multiple ice categories (NOT implemented) Milbrandt and Morrison (2016)

  4. Milbrandt et al. (2025) - Predicted liquid fraction: shedding, refreezing Milbrandt et al. (2025)

Source Code

Based on P3-microphysics v5.5.0

Not Implemented

  • Three-moment ice (prognostic reflectivity) from Milbrandt et al. (2021)
  • Multiple free ice categories from Milbrandt & Morrison (2016)
  • Lookup table I/O for all table types
source
Breeze.Microphysics.PredictedParticleProperties.AerosolActivation — Method
AerosolActivation(
    mode1::Breeze.Microphysics.PredictedParticleProperties.AerosolMode{FT},
    rest::Breeze.Microphysics.PredictedParticleProperties.AerosolMode{FT}...;
    prognostic=false,
    thermodynamic_constants=ThermodynamicConstants(FT),
    molecular_weight_water=thermodynamic_constants.vapor.molar_mass,
    universal_gas_constant=thermodynamic_constants.molar_gas_constant,
    activation_timescale=1,
    surface_tension_reference=0.0761,
    surface_tension_temperature_derivative=-0.000155,
    surface_tension_reference_temperature=thermodynamic_constants.energy_reference_temperature,
    lognormal_activation_factor=4.242,
    activated_droplet_radius=1.0e-6,
    activation_supersaturation_threshold=1.0e-6,
    minimum_supersaturation=1.0e-20,
    minimum_saturation_mass_fraction=1.0e-20
) where FT -> Breeze.Microphysics.PredictedParticleProperties.AerosolActivation{<:Any, <:Any, <:Tuple{Breeze.Microphysics.PredictedParticleProperties.AerosolMode, Vararg{Breeze.Microphysics.PredictedParticleProperties.AerosolMode}}}

Construct an AerosolActivation from one or more AerosolModes.

The activation timescale $τ_{act}$ controls how quickly the cloud droplet number relaxes toward the activated equilibrium. Default 1.0 s.

Passing an AerosolActivation to P3 makes cloud droplet number prognostic. The prognostic keyword is separate: true carries the unactivated aerosol reservoir $ρn^a$, which activation depletes, while the default false holds the population fixed at the distribution total.

Everything else the activation physics needs is a keyword here rather than a literal in activated_number: the condensate density and molecular weight, the linear surface-tension fit $σ(T) = σ_0 + (dσ/dT)(T - T_{ref})$ whose defaults are water's, the $3\sqrt{2}$ factor of the lognormal activation integral (lognormal_activation_factor, held at the conventional rounded 4.242), the radius of a newly activated droplet, the supersaturation above which activation proceeds, and two floors that keep the supersaturation finite. A condensable species other than water is configured by overriding the first group here and in AerosolMode.

By default, the water molecular weight, liquid-water density, universal gas constant, and surface-tension reference temperature come from thermodynamic_constants.

Examples

using Breeze.Microphysics.PredictedParticleProperties: AerosolActivation, AerosolModeaerosol = AerosolActivation(AerosolMode())length(aerosol.modes)# output1
using Breeze.Microphysics.PredictedParticleProperties: AerosolActivation, AerosolModeaerosol = AerosolActivation(    AerosolMode(number_mixing_ratio=100e6, mean_radius=0.08e-6),    AerosolMode(number_mixing_ratio=50e6,  mean_radius=1.0e-6, geometric_std=2.5);    activation_timescale = 2.0)length(aerosol.modes)# output2

The aerosol population is fixed by default:

using Breeze.Microphysics.PredictedParticleProperties: AerosolActivation, AerosolModesummary(AerosolActivation(AerosolMode()))# output"AerosolActivation(1 mode, fixed reservoir)"
source
Breeze.Microphysics.PredictedParticleProperties.AerosolMode — Type
AerosolMode(
    FT::DataType=Oceananigans.defaults.FloatType;
    number_mixing_ratio=3.0e8,
    mean_radius=5.0e-8,
    geometric_std=2,
    vant_hoff_factor=3,
    osmotic_potential=1,
    mass_fraction_soluble=0.9,
    aerosol_density=1777,
    molecular_weight_aerosol=0.132,
    thermodynamic_constants=ThermodynamicConstants(FT),
    molecular_weight_water=thermodynamic_constants.vapor.molar_mass
) -> Breeze.Microphysics.PredictedParticleProperties.AerosolMode

Construct an AerosolMode representing one component of a multimodal aerosol size distribution. Particles in a mode share one chemical composition and their radii follow a lognormal distribution described by mean_radius and geometric_std. Multiple modes can therefore represent distinct aerosol populations, such as Aitken and accumulation particles.

The solute activity parameter $β_{act} = ν_i ϕ_s ε_m M_w ρ_a / (M_a ρ_w)$ is precomputed at construction time from the chemistry parameters.

Default chemistry is ammonium sulfate (NH₄)₂SO₄.

Keyword Arguments

  • number_mixing_ratio: Aerosol number per unit mass of air [kg⁻¹], default 300×10⁶. With prognostic=true in AerosolActivation, the reservoir ρnᵃ is initialized to air density times the total over all modes once density is available. set! repeats this initialization unless nᵃ [kg⁻¹] or ρnᵃ [m⁻³] is supplied.
  • mean_radius: Geometric mean radius [m], default 0.05 μm
  • geometric_std: Geometric standard deviation [-], default 2
  • vant_hoff_factor: van't Hoff factor [-], default 3
  • osmotic_potential: Osmotic potential [-], default 1
  • mass_fraction_soluble: Mass fraction soluble [-], default 0.9
  • aerosol_density: Aerosol density [kg/m³], default 1777
  • molecular_weight_aerosol: Molecular weight of aerosol [kg/mol], default 0.132
  • thermodynamic_constants: Constants supplying the water molecular weight and liquid-water density
  • molecular_weight_water: Molecular weight of the condensate [kg/mol], default thermodynamic_constants.vapor.molar_mass

The molecular weight and thermodynamic_constants.liquid.density enter only through $β_{act}$. A condensable species other than water is configured through thermodynamic_constants and the surface-tension fit in AerosolActivation.

References

Morrison and Grabowski (2007)

Examples

using Breeze.Microphysics.PredictedParticleProperties: AerosolModemode = AerosolMode()mode.mean_radius# output5.0e-8
source
Breeze.Microphysics.PredictedParticleProperties.CloudDroplets — Type
CloudDroplets(
    FT=Oceananigans.defaults.FloatType;
    number_concentration=2.0e8,
    condensation_timescale=1,
    shape=CloudShape(FT),
    shape_parameter=nothing
) -> Breeze.Microphysics.PredictedParticleProperties.CloudDroplets

Construct CloudDroplets with prescribed parameters.

Cloud droplets in P3 are treated simply: their number concentration is prescribed rather than predicted. This is a common simplification appropriate for many applications where aerosol-cloud interactions are not the focus.

Why prescribe Nᶜˡ?

Predicting cloud droplet number Nᶜˡ requires treating aerosol activation physics, which adds substantial complexity. For simulations focused on ice processes or bulk precipitation, prescribed Nᶜˡ is sufficient.

The prescribed-Nᶜˡ simplification means: (1) homogeneous freezing below −40°C transfers the prescribed Nᶜˡ rather than a locally depleted droplet count, and (2) autoconversion sensitivity to Nᶜˡ is controlled by the prescribed value rather than dynamically. Pass aerosol = AerosolActivation(AerosolMode()) to predict Nᶜˡ instead.

There is no separate mass-number consistency cap on homogeneous freezing: homogeneous_freezing_cloud_rate transfers all of Nᶜˡ at T < homogeneous_freezing_temperature. compute_p3_process_rates diagnoses the rate from the post-process residual cloud and rescales mass and number together by a single sink_limiting_factor. This limits the frozen mass to the residual cloud while preserving its diagnosed mass-number ratio; it does not impose a minimum frozen-particle mass or independently limit the transferred number.

Cloud DSD shape parameter: Process rates diagnose μᶜˡ from the local droplet concentration via liu_daum_shape_parameter, using the relation and bounds in shape. This applies to both prescribed and prognostic droplet number. Configure shape for sensitivity studies that change the simulated PSD.

The shape_parameter keyword replaces the value stored in the shape_parameter field. It does not change the PSD or freezing rates used in a simulation.

The stored freezing_psd_correction = Γ(μᶜˡ+7)Γ(μᶜˡ+1)/Γ(μᶜˡ+4)² is evaluated at shape_parameter. immersion_freezing_cloud_rate recomputes the correction from the local μᶜˡ with psd_correction_spherical_volume.

Typical values:

  • Continental: Nᶜˡ ~ 100-300 × 10⁶ m⁻³ → μᶜˡ ~ 4–8
  • Marine: Nᶜˡ ~ 50-100 × 10⁶ m⁻³ → μᶜˡ ~ 8–10

Autoconversion: Cloud droplets are converted to rain via collision-coalescence following Khairoutdinov and Kogan (2000).

Keyword Arguments

  • number_concentration: Nᶜˡ [1/m³], default 200×10⁶
  • condensation_timescale: Saturation relaxation [s], default 1.0. The coupled adjustment uses ProcessRate.sink_limiting_timescale instead.
  • shape: CloudShape holding the coefficients and bounds of the Liu-Daum relation, default CloudShape(FT). Read by every path that diagnoses μᶜˡ from a local droplet number.
  • shape_parameter: μᶜˡ for cloud gamma PSD [-], default nothing (diagnosed from Nᶜˡ via Liu-Daum relation). Pass an explicit value to override the construction-time diagnosis only.

References

Morrison and Milbrandt (2015a), Khairoutdinov and Kogan (2000).

Examples

using Oceananigans, Breezeusing Breeze.Microphysics.PredictedParticleProperties: CloudDropletscloud = CloudDroplets()round(cloud.shape_parameter, digits=1)  # μᶜˡ diagnosed from Nᶜˡ = 200×10⁶ m⁻³# output5.7
source
Breeze.Microphysics.PredictedParticleProperties.CloudShape — Type
CloudShape(
    FT::DataType=Oceananigans.defaults.FloatType;
    relative_dispersion_number_coefficient=5.714e-10,
    relative_dispersion_intercept=0.2714,
    minimum_shape_parameter=2,
    maximum_shape_parameter=15
) -> Breeze.Microphysics.PredictedParticleProperties.CloudShape

Construct CloudShape.

Keyword Arguments

  • relative_dispersion_number_coefficient: $\mathbb{C}_{cl,1}$ [m³], default 5.714e-10
  • relative_dispersion_intercept: $\mathbb{C}_{cl,2}$ [-], default 0.2714
  • minimum_shape_parameter: $\mathbb{C}_{cl,3}$ [-], default 2
  • maximum_shape_parameter: $\mathbb{C}_{cl,4}$ [-], default 15

Examples

using Breeze.Microphysics.PredictedParticleProperties: CloudShapeCloudShape(Float64)# outputCloudShape(ℂᶜˡ₁=5.714e-10 m³, ℂᶜˡ₂=0.2714, ℂᶜˡ₃=2.0, ℂᶜˡ₄=15.0)
source
Breeze.Microphysics.PredictedParticleProperties.CloudShape — Type
CloudShape{FT}

Coefficients of the Liu-Daum (2000)-type relation that diagnoses the cloud gamma PSD shape parameter $μ^{cl}$ from the droplet number density, together with the bounds the diagnosis is clamped to. Evaluated by liu_daum_shape_parameter:

\[\chi = \mathbb{C}_{cl,1} \, N^{cl} + \mathbb{C}_{cl,2}, \qquad \mu^{cl} = \mathrm{clamp}\!\left(\frac{1}{\chi^2} - 1,\; \mathbb{C}_{cl,3},\; \mathbb{C}_{cl,4}\right)\]

$\chi$ is the relative dispersion of the droplet spectrum, and $(\mathbb{C}_{cl,1}, \mathbb{C}_{cl,2})$ are the Liu-Daum regression of $\chi$ on droplet concentration, fit to aircraft measurements of warm cloud droplet spectra: at fixed water content, more droplets means a narrower spectrum, hence a larger $μ^{cl}$. The free parameters $(\mathbb{C}_{cl,3}, \mathbb{C}_{cl,4})$ bound $μ^{cl}$ to the range over which the fit was measured.

The coefficient is stated here for the absolute number density in SI units [m⁻³], so $\mathbb{C}_{cl,1}$ carries units of m³. The published form uses cm⁻³, hence the 10⁻⁶ difference from the printed 5.714 × 10⁻⁴.

See the constructor for the meaning, units and defaults of each coefficient.

source
Breeze.Microphysics.PredictedParticleProperties.IceBulk — Type
IceBulk(
    FT::DataType=Oceananigans.defaults.FloatType;
    maximum_mean_diameter=0.02,
    minimum_mean_diameter=2.0e-6
) -> Breeze.Microphysics.PredictedParticleProperties.IceBulk{<:Any, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}

Construct IceBulk with parameters and quadrature-based integrals.

These integrals compute bulk properties by averaging over the particle size distribution. They are used for radiation, radar, and diagnostics.

Diagnostic integrals:

  • effective_radius: Radiation-weighted radius $r_e = (3/(4ρ_i^*)) ∫m·N'dD / ∫A·N'dD$, with the table generator's reference ice density $ρ_i^* = 916.7$ kg/m³
  • mean_diameter: Mass-weighted diameter $D_m = ∫D·m·N'dD / ∫m·N'dD$
  • mean_density: Mass-weighted density $ρ̄ = ∫ρ·m·N'dD / ∫m·N'dD$
  • reflectivity: Number-normalized equivalent radar reflectivity. Dry ice uses $0.1892 ∫D_{eq}^6 N'dD / ∫N'dD$, with equivalent diameter computed from particle mass at 917 kg/m³. Partially melted ice uses the generator's wet-ice scattering calculation; the fully liquid limit uses $D^6$. Multiply by ice number density for the volume integral.

Tabulated distribution parameters:

  • slope: Slope parameter λ recorded when the table was generated
  • shape: Shape parameter μⁱ recorded when the table was generated, read back by compute_ice_shape_parameter

Process integrals:

  • shedding: Rate at which meltwater sheds from large particles

Keyword Arguments

  • maximum_mean_diameter: Upper Dm limit [m], default 0.02 (2 cm)
  • minimum_mean_diameter: Lower Dm limit [m], default 2×10⁻⁶ (2 μm)

References

Morrison and Milbrandt (2015a), Field et al. (2007) for μⁱ-λ relationship.

source
Breeze.Microphysics.PredictedParticleProperties.IceCollection — Method
IceCollection() -> Breeze.Microphysics.PredictedParticleProperties.IceCollection{Nothing, Nothing, Nothing, Nothing}

Construct IceCollection with placeholder (nothing) integrals, following the materialization pattern: read_lookup_tables replaces each field with the corresponding tabulated integral.

Collection processes describe ice particles sweeping up other hydrometeors through gravitational settling. The integrals held here are the ones that depend on the ice size distribution alone:

Aggregation (ice + ice → larger ice): Ice particles collide and stick together to form larger aggregates. This is the dominant growth mechanism for snow, and depends on the differential fall speeds of particles of different sizes. Consumed by ice_aggregation_rate.

Cloud collection (ice + cloud droplets → rime on ice): The PSD-integrated sweep-out kernel $\int \mathbb{W}(D) A(D) N'(D) \, dD$ [m³/s] per particle, with the collision kernel set to zero for ice diameters below 100 μm. Cloud droplets are small enough relative to ice that their own size distribution does not enter the collision geometry, so a single ice-PSD integral suffices. Consumed by cloud_riming_rate below freezing and by cloud_warm_collection_rate above it.

Aerosol scavenging (cloud_aerosol_collection, ice_aerosol_collection): Collection by ice particles of water-friendly and ice-friendly interstitial aerosol, respectively.

Ice-rain collection is handled separately, by IceRainCollection and the 5D rain-ice block embedded in Lookup Table 1, because its kernel needs the rain slope parameter $λ_r$ in addition to the ice PSD.

Collection efficiencies are not stored here. They live in ProcessRate alongside the other rate parameters, as cloud_ice_collection_efficiency ($E^{ci}$) and rain_ice_collection_efficiency ($E^{ri}$).

References

Morrison and Milbrandt (2015a) Sections 2d-e, Milbrandt and Yau (2005).

source
Breeze.Microphysics.PredictedParticleProperties.IceDeposition — Type
IceDeposition(
    ::DataType=Oceananigans.defaults.FloatType
) -> Breeze.Microphysics.PredictedParticleProperties.IceDeposition{Nothing, Nothing, Nothing, Nothing, Nothing, Nothing}

Construct IceDeposition with quadrature-based ventilation integrals.

Ice growth/decay by vapor deposition/sublimation follows the diffusion equation with ventilation enhancement. The ventilation factor $fᵛᵉ$ accounts for enhanced vapor transport due to particle motion through air:

\[fᵛᵉ = a + b \cdot Sc^{1/3} Re^{1/2}\]

where $Sc$ is the Schmidt number and $Re$ is the Reynolds number. Hall and Pruppacher (1976) showed that falling particles have significantly enhanced vapor exchange compared to stationary particles.

Thermal conductivity $κ$ and vapor diffusivity $Dᵥ$ are computed at runtime from temperature, pressure, and the model thermodynamic constants via air_transport_properties(T, P, constants). They are not stored on IceDeposition.

Basic ventilation integrals:

  • ventilation: Integrated over full size spectrum
  • enhanced_ventilation: For larger particles (D > 100 μm)

Size-regime ventilation (for melting with liquid fraction):

  • small_ice_ventilation_*: D ≤ Dcrit, meltwater → rain
  • large_ice_ventilation_*: D > Dcrit, meltwater → liquid on ice

References

Hall and Pruppacher (1976), Morrison and Milbrandt (2015a) Eq. 34.

source
Breeze.Microphysics.PredictedParticleProperties.IceFallSpeed — Type
IceFallSpeed(
    FT::DataType=Oceananigans.defaults.FloatType;
    thermodynamic_constants=ThermodynamicConstants(FT),
    reference_pressure=60000,
    reference_temperature=253.15,
    reference_air_density=reference_pressure / (dry_air_gas_constant(thermodynamic_constants) * reference_temperature)
) -> Breeze.Microphysics.PredictedParticleProperties.IceFallSpeed{<:Any, Nothing, Nothing}

Construct IceFallSpeed with parameters and quadrature-based integrals.

Ice particle terminal velocity uses the Mitchell and Heymsfield (2005) Best-number formulation with air density correction exponent 0.54 from Heymsfield et al. (2007). The reference density $ρ₀ = p₀ / (Rᵈ T₀)$ is the dry-air density at the reference conditions at which the P3 lookup tables are computed, $T₀ = 253.15$ K and $p₀ = 600$ hPa, and comes out at ≈0.825 kg/m³. It is not the surface reference density ≈1.275 kg/m³ that corrects rain fall speeds.

Two weighted fall speeds are computed by integrating over the size distribution:

  • Number-weighted $\mathbb{W}^n$: For number flux (sedimentation of particle count)
  • Mass-weighted $\mathbb{W}^m$: For mass flux (precipitation rate)

Keyword Arguments

  • thermodynamic_constants: Source of the dry-air gas constant used to diagnose the default reference-air density.
  • reference_pressure: Pressure $p₀$ [Pa] of the lookup-table reference state.
  • reference_temperature: Temperature $T₀$ [K] of the lookup-table reference state.
  • reference_air_density: Reference $ρ₀$ [kg/m³], by default diagnosed from reference_pressure and reference_temperature.

References

Morrison and Milbrandt (2015a) Eq. 20.

source
Breeze.Microphysics.PredictedParticleProperties.IceLambdaLimiter — Method
IceLambdaLimiter() -> Breeze.Microphysics.PredictedParticleProperties.IceLambdaLimiter{Nothing, Nothing}

Construct IceLambdaLimiter with quadrature-based integrals.

The slope parameter λ of the gamma size distribution can become unrealistically large or small as prognostic moments evolve. This happens at edges of mixed-phase regions or during rapid microphysical adjustments.

Physical interpretation:

  • Very large λ → all particles tiny (mean size → 0)
  • Very small λ → all particles huge (mean size → ∞)

The columns store inverse mean particle masses [kg⁻¹] at the limiting PSDs. Multiplying them by total ice mass fraction (including liquid coating) gives the bounds on nⁱ:

  • small_q: inverse minimum mean mass, giving the maximum number at the upper λ bound
  • large_q: inverse maximum mean mass, giving the minimum number at the lower λ bound

The limiter ensures the diagnosed size distribution remains physically sensible even when the prognostic constraints become degenerate.

References

Morrison and Milbrandt (2015a) Section 2b.

source
Breeze.Microphysics.PredictedParticleProperties.IceParticles — Type
IceParticles(
    FT::DataType=Oceananigans.defaults.FloatType;
    thermodynamic_constants=ThermodynamicConstants(FT),
    minimum_rime_density=50,
    maximum_rime_density=900,
    maximum_shape_parameter=20
)

Construct ice particle properties with parameters and integrals for the P3 scheme.

Ice particles in P3 span a continuum from small pristine crystals to large heavily-rimed graupel. The particle mass $m(D)$ follows a piecewise power law depending on size $D$, rime fraction $Fᶠ$, and rime density $ρᶠ$.

Physical Concepts

This container organizes all ice-related computations:

  • Fall speed: Terminal velocity integrals for sedimentation (number-weighted, mass-weighted)
  • Deposition: Ventilation integrals for vapor diffusion growth
  • Bulk properties: Population-averaged diameter, density, reflectivity
  • Collection: Integrals for aggregation and riming rates
  • Lambda limiter: Constraints on size distribution slope
  • Ice-rain collection: Double-PSD integrals for ice-rain interaction

Keyword Arguments

  • thermodynamic_constants: Source of constants used by the ice-property defaults.
  • minimum_rime_density: Lower bound for ρᶠ [kg/m³], default 50
  • maximum_rime_density: Upper bound for ρᶠ [kg/m³], default 900 (pure ice)
  • maximum_shape_parameter: Upper limit on μⁱ [-], default 20

References

The mass-diameter relationship is from Morrison and Milbrandt (2015a).

source
Breeze.Microphysics.PredictedParticleProperties.IceRainCollection — Method
IceRainCollection() -> Breeze.Microphysics.PredictedParticleProperties.IceRainCollection{Nothing, Nothing}

Construct a placeholder IceRainCollection with nothing fields.

The actual ice-rain collection integrals are double integrals over both the ice and rain size distributions, tabulated offline in the P3 lookup tables. This placeholder is overwritten when tables are loaded via read_lookup_tables.

References

Morrison and Milbrandt (2015a).

source
Breeze.Microphysics.PredictedParticleProperties.NumericalFloors — Type
NumericalFloors(
    FT::DataType=Oceananigans.defaults.FloatType;
    saturation_mass_fraction=1.0e-10,
    transport_coefficient=1.0e-10,
    mass_scale=1.0e-20,
    number_scale=1.0e-16,
    rate_scale=1.0e-20,
    divisor=1.0e-30,
    mean_particle_mass_fallback=1.0e-12
) -> Breeze.Microphysics.PredictedParticleProperties.NumericalFloors

Construct the numerical floors shared by the P3 process rates: the smallest value each quantity is allowed to take before it enters a division or a logarithm, so that a process rate stays finite where the physics may legitimately reach zero. divisor is the last resort — the smallest strictly positive number substituted for anything that would otherwise send a quotient or a logarithm to infinity. mean_particle_mass_fallback is the one entry that replaces a quantity outright rather than bounding it, standing in for a mean particle mass where the number concentration is exactly zero.

Each value is a field rather than a literal so that a configuration can move all of them together. The defaults sit far below any atmospheric value at double precision and remain normal numbers in Float32, whose smallest normal is $1.2 × 10^{-38}$. They do not survive Float16, whose smallest normal is $6.1 × 10^{-5}$ — half precision needs floors raised into that range, which is the reason they are settable rather than baked in.

using Breeze.Microphysics.PredictedParticleProperties: NumericalFloorsNumericalFloors(Float64)# outputNumericalFloors(mass_scale=1.0e-20)
source
Breeze.Microphysics.PredictedParticleProperties.P3MicrophysicalState — Type
P3MicrophysicalState{FT} <: AbstractMicrophysicalState{FT}

Microphysical state for P3 (Predicted Particle Properties) microphysics.

Contains the local mixing ratios and number concentrations needed to compute tendencies for cloud liquid, rain, ice, rime, and predicted liquid fraction.

Fields

  • qᶜˡ::Any: Cloud liquid mixing ratio [kg/kg]

  • nᶜˡ::Any: Cloud number concentration [1/kg]

  • qʳ::Any: Rain mixing ratio [kg/kg]

  • nʳ::Any: Rain number concentration [1/kg]

  • qⁱ::Any: Ice mixing ratio [kg/kg]

  • nⁱ::Any: Ice number concentration [1/kg]

  • qᶠ::Any: Rime mass mixing ratio [kg/kg]

  • bᶠ::Any: Rime volume [m³/kg]

  • qʷⁱ::Any: Liquid water on ice mixing ratio [kg/kg]

  • δqᵛ⁺ˡ::Any: Vapor excess over liquid [kg/kg] (Grabowski & Morrison 2008)

  • nᵃ::Any: Unactivated aerosol number concentration [1/kg] (zero when no aerosol prognostic)

  • w::Any: Cell-center vertical velocity [m/s]; drives the adiabatic temperature tendency

source
Breeze.Microphysics.PredictedParticleProperties.PredictedParticlePropertiesMicrophysics — Type
PredictedParticlePropertiesMicrophysics(
    FT::DataType=Oceananigans.defaults.FloatType;
    lookup_tables=artifact"P3_lookup_tables",
    thermodynamic_constants=ThermodynamicConstants(FT),
    minimum_mass_mixing_ratio=1.0e-14,
    minimum_number_mixing_ratio=1.0e-16,
    precipitation_boundary_condition=nothing,
    negative_moisture_correction=SpeciesBorrowing(),
    aerosol=nothing,
    cloud=nothing,
    rain=nothing,
    process_rates=nothing,
    vapor_excess=DiagnosticVaporExcess(),
    liquid_fraction=PrognosticLiquidFraction(),
    warm_rain_scheme=KhairoutdinovKogan2000()
)

Construct the Predicted Particle Properties (P3) microphysics scheme.

P3 is a bulk microphysics scheme that uses a single ice category with continuously predicted properties, rather than discrete categories like cloud ice, snow, graupel, and hail. As ice particles grow and rime, their properties evolve smoothly without artificial category conversions.

Physical Concept

Traditional schemes force growing ice particles through discrete transitions:

cloud ice → snow → graupel → hail

Each transition requires ad-hoc conversion parameters. P3 instead tracks:

  • Rime fraction $Fᶠ$: What fraction of mass is rime?
  • Rime density $ρᶠ$: How dense is the rime layer?
  • Liquid fraction $Fˡ$: Liquid water coating from partial melting

From these, particle characteristics (mass, fall speed, collection efficiency) are diagnosed continuously.

Two-Moment Ice

The scheme carries two prognostic moments for ice particles:

  1. Mass ($qⁱ$): Total ice mass
  2. Number ($nⁱ$): Ice particle number concentration

Prognostic Variables

The scheme tracks 8 prognostic densities by default, and up to 11 with every option on:

VariableDescriptionCarried when
$ρqᶜˡ$Cloud liquid massalways
$ρqʳ$, $ρnʳ$Rain mass and numberalways
$ρqⁱ$, $ρnⁱ$Ice mass and numberalways
$ρqᶠ$, $ρbᶠ$Rime mass and volumealways
$ρqʷⁱ$Liquid water on icealways
$ρδqᵛ⁺ˡ$Prognostic vapor excess over liquidvapor_excess = PrognosticVaporExcess()
$ρnᶜˡ$Cloud droplet numberaerosol
$ρnᵃ$Unactivated aerosol numberaerosol, with prognostic

Optional fields are allocated and advected only when enabled.

Keyword Arguments

  • thermodynamic_constants: Source of shared phase and dry-air properties.
  • lookup_tables: Path to a directory containing P3 lookup table files (default to the artifact P3_lookup_tables in Artifacts.toml).
  • minimum_mass_mixing_ratio: Mass below which a species is treated as absent [kg/kg] (default 10⁻¹⁴)
  • minimum_number_mixing_ratio: Number below which a population is treated as absent [kg⁻¹] (default 10⁻¹⁶)
  • cloud: CloudDroplets holding the prescribed droplet number and the CloudShape every μᶜˡ diagnosis reads. nothing (default) uses CloudDroplets(FT).
  • rain: RainDrops skeleton holding the RainFallSpeed the startup quadrature integrates and the RainVentilation the evaporation and coupled-adjustment rates read. nothing (default) uses RainDrops(FT). Its lookup fields are materialized by read_lookup_tables; every supplied parameter is preserved.
  • vapor_excess: DiagnosticVaporExcess (default) diagnoses the vapor excess over liquid from the thermodynamic state; PrognosticVaporExcess carries $ρδqᵛ⁺ˡ$ as a prognostic field. Ignored when process_rates is supplied.
  • liquid_fraction: PrognosticLiquidFraction (default) tracks liquid water on ice; NoLiquidFraction routes that liquid to rain. Ignored when process_rates is supplied.
  • precipitation_boundary_condition: Boundary condition for surface precipitation. nothing (default) is an open surface: the diagnosed fall speed is retained at the bottom face, so all sedimenting species leave the domain. ImpenetrableBoundaryCondition() zeroes the fall speed there instead, so precipitation accumulates in the lowest cell.
  • negative_moisture_correction: Repair of negative densities left by the advection operator, applied at the top of update_state!. Defaults to SpeciesBorrowing(), which borrows along the chain $ρqʷⁱ ← ρqⁱ ← ρqʳ ← ρqᶜˡ ← ρqᵛ$, zeroes number and rime fields orphaned by a vanishing ice mass, and clamps negative number and rime densities. Pass SpeciesBorrowing(vertical_borrowing = VerticalBorrowing()) to additionally redistribute leftover vapor deficits within each column, or nothing to disable the repair (P3's process rates then see zero-clamped values while the prognostic fields keep their negative mass).

Cloud Droplet Activation

By default, cloud droplet concentration is prescribed by cloud.number_concentration. Pass aerosol = AerosolActivation(AerosolMode()) to predict droplet number from aerosol activation. Set prognostic=true in AerosolActivation to also track depletion of the unactivated aerosol reservoir.

Configuring the empirical warm-phase parameters

The cloud-width, rain fall-speed, and rain-ventilation fits are each owned by a small parameter container that is visible from this constructor. Custom values are threaded through the startup quadrature and every runtime kernel:

using Breezeusing Breeze.Microphysics.PredictedParticleProperties:    CloudDroplets, CloudShape,    RainDrops, RainFallSpeed, RainVentilationcloud = CloudDroplets(Float64;    shape = CloudShape(Float64; maximum_shape_parameter = 12))rain = RainDrops(Float64;    fall_speed = RainFallSpeed(Float64; plateau_velocity = 9.5),    ventilation = RainVentilation(Float64; reynolds_coefficient = 0.35))p3 = P3Microphysics(Float64; cloud, rain)p3.rain.ventilation# outputRainVentilation(ℂᵛᵉⁿᵗ₁=0.78, ℂᵛᵉⁿᵗ₂=0.35)

Example

using Breeze# The `P3_lookup_tables` artifact is lazy: Pkg downloads it on first usemicrophysics = PredictedParticlePropertiesMicrophysics()# outputPredictedParticlePropertiesMicrophysics├── ρʷ: 1000.0 kg/m³├── qmin: 1.0e-14 kg/kg├── ice: IceParticles├── rain: RainDrops├── cloud: CloudDroplets├── process_rates: ProcessRate├── negative_moisture_correction: SpeciesBorrowing(vertical_borrowing = nothing)├── aerosol: nothing (prescribed droplet number)└── warm_rain_scheme: KhairoutdinovKogan2000

References

This implementation follows P3 v5.5 from the P3-microphysics repository.

Key papers describing P3:

See also the P3 documentation for detailed physics.

source
Breeze.Microphysics.PredictedParticleProperties.ProcessRate — Type
ProcessRate(
    FT::DataType=Oceananigans.defaults.FloatType;
    thermodynamic_constants=ThermodynamicConstants(FT),
    freezing_temperature=273.15,
    reference_pressure=100000,
    reference_temperature=273.15,
    reference_air_density=reference_pressure / (dry_air_gas_constant(thermodynamic_constants) * reference_temperature),
    fall_speed_density_correction_exponent=0.54,
    minimum_fall_speed_air_density=0.01,
    nucleated_ice_radius=1.0e-6,
    nucleated_ice_density=900.0,
    nucleated_ice_mass=((4 * FT(π)) / 3) * nucleated_ice_density * nucleated_ice_radius ^ 3,
    activated_droplet_radius=1.0e-6,
    activation_supersaturation_threshold=1.0e-6,
    autoconversion_coefficient=1350 * 100.0 ^ -1.79,
    autoconversion_exponent_cloud=2.47,
    autoconversion_exponent_droplet=-1.79,
    autoconversion_threshold=1.0e-8,
    autoconversion_reference_concentration=1.0e8,
    accretion_coefficient=67.0,
    accretion_exponent=1.15,
    rain_self_collection_coefficient=5.78,
    rain_breakup_diameter_threshold=0.00028,
    rain_breakup_coefficient=2300.0,
    rain_evaporation_timescale=10.0,
    maximum_aggregation_efficiency=0.3,
    minimum_aggregation_efficiency=0.001,
    aggregation_efficiency_ramp_start_temperature=253.15,
    aggregation_efficiency_ramp_end_temperature=273.15,
    minimum_aggregation_rime_fraction=0.6,
    maximum_aggregation_rime_fraction=0.9,
    cloud_ice_collection_efficiency=0.5,
    rain_ice_collection_efficiency=1.0,
    minimum_rime_density=50.0,
    maximum_rime_density=900.0,
    rime_impact_coefficient=500000.0,
    minimum_rime_impact=1.0,
    maximum_rime_impact=12.0,
    minimum_riming_supercooling=0.001,
    unrimed_rime_density=400.0,
    rime_density_constant_coefficient=51.0,
    rime_density_linear_coefficient=114.0,
    rime_density_quadratic_coefficient=-5.5,
    rime_density_transition_impact=8.0,
    shed_drop_diameter=0.001,
    shed_drop_mass=(FT(π) / 6) * thermodynamic_constants.liquid.density * shed_drop_diameter ^ 3,
    shed_drop_mass_liqfrac=shed_drop_mass,
    wet_growth_hydrometeor_threshold=1.0e-6,
    wet_growth_excess_threshold=1.0e-10,
    refreezing_timescale=10.0,
    ice_nucleation_temperature_threshold=258.15,
    ice_nucleation_supersaturation_threshold=0.05,
    maximum_ice_nucleation_concentration=100000.0,
    ice_nucleation_timescale=10.0,
    ice_nucleation_coefficient=5.0,
    ice_nucleation_temperature_coefficient=0.304,
    maximum_immersion_freezing_temperature=269.15,
    immersion_freezing_coefficient=0.65,
    immersion_freezing_nucleation_coefficient=2.0,
    minimum_splintering_temperature=265.15,
    maximum_splintering_temperature=270.15,
    splintering_temperature_peak=268.15,
    splintering_rate=3.5e8,
    splintering_crystal_diameter=1.0e-5,
    splintering_crystal_density=nucleated_ice_density,
    splintering_crystal_mass=(FT(π) / 6) * splintering_crystal_density * splintering_crystal_diameter ^ 3,
    splintering_diameter_threshold=0.00025,
    splintering_cloud_riming_scale=1.0,
    maximum_splintering_liquid_fraction=0.1,
    maximum_splintering_surface_temperature=282.0,
    initial_rain_drop_mass=((4 * FT(π)) / 3) * thermodynamic_constants.liquid.density * 2.5e-5 ^ 3,
    homogeneous_freezing_temperature=233.15,
    homogeneous_freezing_timescale=10.0,
    rime_densification_timescale=10.0,
    maximum_mean_droplet_diameter=4.0e-5,
    minimum_mean_droplet_diameter=1.0e-6,
    minimum_rain_slope=500.0,
    maximum_rain_slope=100000.0,
    sink_limiting_timescale=10.0,
    coupled_sink_limiting_iterations::Integer=4,
    maximum_ice_number_density=2.0e6,
    liquid_fraction_clipping_threshold=0.01,
    complete_melting_liquid_fraction=0.99,
    tiny_ice_to_rain_threshold=1.0e-12,
    tiny_mass_evaporation_threshold=1.0e-12,
    subsaturation_evaporation_threshold=0.001,
    liquid_fraction=PrognosticLiquidFraction(),
    vapor_excess=DiagnosticVaporExcess(),
    calibration_factor_deposition=1.0,
    calibration_factor_sublimation=1.0,
    floors=NumericalFloors(FT)
) -> Breeze.Microphysics.PredictedParticleProperties.ProcessRate{<:Any, DiagnosticVaporExcess, PrognosticLiquidFraction}

Construct process rate parameters with default values from P3 literature.

The liquid-water density, the pure-ice density, and the dry-air gas constant used by the reference-density calculation come from the supplied thermodynamic_constants. The default shed_drop_mass and initial_rain_drop_mass also use that liquid-water density. The default nucleated_ice_mass uses nucleated_ice_density (900 kg/m³), while splintering_crystal_mass uses splintering_crystal_density, which defaults to nucleated_ice_density. Both ice seed densities are configurable independently of pure_ice_density.

These parameters control the rates of all microphysical processes: autoconversion, accretion, aggregation, riming, melting, evaporation, deposition, nucleation, and freezing.

The fresh-rime density polynomial has configurable rime_density_constant_coefficient, rime_density_linear_coefficient, and rime_density_quadratic_coefficient (all in kg/m³, since the impact parameter is dimensionless). rime_density_transition_impact selects the start of its linear extension. The extension is continuous and reaches maximum_rime_density at maximum_rime_impact; its intercept and slope are derived, not independent parameters. The impact bounds must satisfy minimum_rime_impact ≤ rime_density_transition_impact < maximum_rime_impact.

Calibratable empirical values are denoted $\mathbb{C}$ in the theory. When a kernel unpacks one into a formula-local variable, the implementation uses the matching Unicode identifier, such as ℂᵃᵘᵗᵒ₁. The public fields and constructor keywords remain descriptive; each calibratable field comment records its exact ℂ symbol. Physical constants, case inputs, switches, and numerical safeguards do not receive ℂ. See the complete calibration inventory.

Ice terminal-velocity, projected-area, collection, and ventilation integrals are read from the P3 lookup tables by read_lookup_tables. Rain velocity and evaporation integrals are generated with Julia quadrature. Cloud PSD shape is diagnosed from droplet number, while the active rain-process path uses $μ_r = 0$. None are duplicated in this rate-parameter container.

Default Sources

  • Autoconversion/accretion: Khairoutdinov and Kogan (2000)
  • Self-collection: Khairoutdinov and Kogan (2000); breakup: Verlinde and Cotton (1993)
  • Aggregation: Morrison and Milbrandt (2015)
  • Nucleation: Cooper (1986)
  • Freezing: Barklie and Gokhale (1959)
  • Splintering: Hallett and Mossop (1974)

Example

The second and third type parameters are the types of vapor_excess and liquid_fraction. The default DiagnosticVaporExcess() drops ρδqᵛ⁺ˡ from the prognostic set entirely.

using Breeze.Microphysics.PredictedParticleProperties: ProcessRate, DiagnosticVaporExcess,                                                       PrognosticLiquidFractionparams = ProcessRate(Float64)typeof(params)# outputProcessRate{Float64, DiagnosticVaporExcess, PrognosticLiquidFraction}

All parameters are keyword arguments with physically-based defaults. The coupled donor-budget limiter uses four re-projection passes by default; set coupled_sink_limiting_iterations to tune that count.

source
Breeze.Microphysics.PredictedParticleProperties.RainDrops — Type
RainDrops(
    FT::DataType=Oceananigans.defaults.FloatType;
    fall_speed=RainFallSpeed(FT),
    ventilation=RainVentilation(FT)
) -> Breeze.Microphysics.PredictedParticleProperties.RainDrops{<:Any, Nothing, Nothing, Nothing}

Construct RainDrops with empirical parameters and quadrature-based integrals.

Rain in P3 follows an exponential size distribution, the $μ^r = 0$ special case of the gamma distribution used for ice:

\[N'(D) = Nʳ₀ e^{-λ^r D}\]

There is no rain shape parameter, prognostic or diagnosed: rain_slope_parameter inverts the mass integral directly as $λ^r = (π ρ^w n^r / q^r)^{1/3}$, and rain_quadrature.jl integrates against the same exponential kernel.

Terminal velocity: the piecewise Gunn-Kinzer / Beard law of rain_fall_speed, configured by fall_speed. It is not a single power law; the four regimes capture Stokes drag below the first transition diameter ($D ≈ 134$ μm by default) and the terminal-velocity plateau above the third ($D ≈ 3.5$ mm).

Ventilation: $f^{ve} = \mathbb{C}_{\mathrm{vent},1} + \mathbb{C}_{\mathrm{vent},2}\,\mathrm{Sc}^{1/3}\,\mathrm{Re}^{1/2}$, configured by ventilation and consumed by rain evaporation and by the coupled saturation-adjustment relaxation coefficient.

Integrals: this is a skeleton — velocity_number, velocity_mass and evaporation are nothing until tabulate_rain_from_quadrature materializes them from fall_speed. Both parameter containers are preserved verbatim across materialization.

Spectrum bounds: set by ProcessRate.minimum_rain_slope and maximum_rain_slope through rain_slope_parameter, not by this container.

Keyword Arguments

References

Morrison and Milbrandt (2015a), Milbrandt and Yau (2005), Seifert and Beheng (2006).

Examples

using Breeze.Microphysics.PredictedParticleProperties: RainDrops, RainVentilationrain = RainDrops(Float64; ventilation = RainVentilation(Float64;                                                   constant_coefficient = 0.8))rain.ventilation# outputRainVentilation(ℂᵛᵉⁿᵗ₁=0.8, ℂᵛᵉⁿᵗ₂=0.32)
source
Breeze.Microphysics.PredictedParticleProperties.RainFallSpeed — Type
RainFallSpeed(
    FT::DataType=Oceananigans.defaults.FloatType;
    branch_velocity_scales=(4579.5, 49.62, 17.32),
    branch_mass_exponents=(2 / 3, 1 / 3, 1 / 6),
    transition_diameters=(0.00013443, 0.00151164, 0.00347784),
    plateau_velocity=9.17
) -> Breeze.Microphysics.PredictedParticleProperties.RainFallSpeed

Construct RainFallSpeed. The defaults reproduce the piecewise Gunn-Kinzer / Beard law used by P3, with the published centimetre-per-second velocity scales converted to SI.

Keyword Arguments

  • branch_velocity_scales: $\mathbb{C}_{\mathrm{fall},1}$ [m/s], default (4579.5, 49.62, 17.32)
  • branch_mass_exponents: $\mathbb{C}_{\mathrm{fall},2}$ [-], default (2/3, 1/3, 1/6)
  • transition_diameters: $\mathbb{C}_{\mathrm{fall},3}$ [m], strictly increasing, default (134.43e-6, 1511.64e-6, 3477.84e-6)
  • plateau_velocity: $\mathbb{C}_{\mathrm{fall},4}$ [m/s], default 9.17

Examples

using Breeze.Microphysics.PredictedParticleProperties: RainFallSpeedRainFallSpeed(Float64)# outputRainFallSpeed(ℂᶠᵃˡˡ₁=(4579.5, 49.62, 17.32) m/s, ℂᶠᵃˡˡ₂=(0.667, 0.333, 0.167), ℂᶠᵃˡˡ₃=(134.43, 1511.64, 3477.84) μm, ℂᶠᵃˡˡ₄=9.17 m/s)
source
Breeze.Microphysics.PredictedParticleProperties.RainFallSpeed — Type
RainFallSpeed{FT}

Empirical coefficients of the piecewise Gunn-Kinzer / Beard rain terminal-velocity law evaluated by rain_fall_speed,

\[\mathbb{W}(D) = \begin{cases} \mathbb{C}_{\mathrm{fall},1,1} \, \hat{m}^{\mathbb{C}_{\mathrm{fall},2,1}} & D \le \mathbb{C}_{\mathrm{fall},3,1} \\ \mathbb{C}_{\mathrm{fall},1,2} \, \hat{m}^{\mathbb{C}_{\mathrm{fall},2,2}} & \mathbb{C}_{\mathrm{fall},3,1} < D < \mathbb{C}_{\mathrm{fall},3,2} \\ \mathbb{C}_{\mathrm{fall},1,3} \, \hat{m}^{\mathbb{C}_{\mathrm{fall},2,3}} & \mathbb{C}_{\mathrm{fall},3,2} \le D < \mathbb{C}_{\mathrm{fall},3,3} \\ \mathbb{C}_{\mathrm{fall},4} & D \ge \mathbb{C}_{\mathrm{fall},3,3} \end{cases}\]

where $\hat{m} = m(D) / (1 \, \mathrm{g})$ is the dimensionless ratio of the drop mass to one gram. The mass itself is the spherical-drop mass at the water density the published fit was derived with (GUNN_KINZER_WATER_DENSITY), which belongs to the fit rather than to the model and is therefore not exposed here.

See the constructor for the meaning, units and defaults of each coefficient.

References

The Gunn-Kinzer / Beard fit as used by P3; see Morrison and Milbrandt (2015a).

source
Breeze.Microphysics.PredictedParticleProperties.RainMassWeightedVelocity — Type
RainMassWeightedVelocity(
    FT::DataType=Oceananigans.defaults.FloatType;
    points::Int64=128,
    floors=NumericalFloors(FT),
    fall_speed=RainFallSpeed(FT)
) -> Breeze.Microphysics.PredictedParticleProperties.RainMassWeightedVelocity{N, W, F, FS} where {N<:(Vector), W<:(Vector), F<:Breeze.Microphysics.PredictedParticleProperties.NumericalFloors, FS<:Breeze.Microphysics.PredictedParticleProperties.RainFallSpeed}

Construct a RainMassWeightedVelocity with points quadrature points, integrating the fall-speed law defined by fall_speed.

source
Breeze.Microphysics.PredictedParticleProperties.RainMassWeightedVelocity — Type
RainMassWeightedVelocity{N, W, F, FS}

Callable evaluator for the mass-weighted rain terminal velocity:

\[\mathbb{W}^m(\lambda_r) = \frac{\int_0^\infty \mathbb{W}(D)\, m(D)\, e^{-\lambda_r D}\, dD} {\int_0^\infty m(D)\, e^{-\lambda_r D}\, dD}\]

where m(D) = (π/6) ρ_w D³ (liquid sphere, ρw = 997 kg/m³) and $\mathbb{W}(D)$ is the piecewise Gunn-Kinzer/Beard rain fall speed from [`rainfall_speed`](@ref) at reference density (no density correction applied here; apply at call site).

Quadrature uses the same exponential-tail transformation as the ice integrals, via chebyshev_gauss_nodes_weights.

source
Breeze.Microphysics.PredictedParticleProperties.RainNumberWeightedVelocity — Type
RainNumberWeightedVelocity(
    FT::DataType=Oceananigans.defaults.FloatType;
    points::Int64=128,
    floors=NumericalFloors(FT),
    fall_speed=RainFallSpeed(FT)
) -> Breeze.Microphysics.PredictedParticleProperties.RainNumberWeightedVelocity{N, W, F, FS} where {N<:(Vector), W<:(Vector), F<:Breeze.Microphysics.PredictedParticleProperties.NumericalFloors, FS<:Breeze.Microphysics.PredictedParticleProperties.RainFallSpeed}

Construct a RainNumberWeightedVelocity with points quadrature points, integrating the fall-speed law defined by fall_speed.

source
Breeze.Microphysics.PredictedParticleProperties.RainVelocityDiameterIntegral — Type
RainVelocityDiameterIntegral(
    FT::DataType=Oceananigans.defaults.FloatType;
    points::Int64=128,
    fall_speed=RainFallSpeed(FT)
) -> Breeze.Microphysics.PredictedParticleProperties.RainVelocityDiameterIntegral{N, W, FS} where {N<:(Vector), W<:(Vector), FS<:Breeze.Microphysics.PredictedParticleProperties.RainFallSpeed}

Construct a RainVelocityDiameterIntegral with points quadrature points, integrating the fall-speed law defined by fall_speed.

source
Breeze.Microphysics.PredictedParticleProperties.RainVelocityDiameterIntegral — Type
RainVelocityDiameterIntegral{N, W, FS}

Callable evaluator for the velocity-diameter part of the rain evaporation ventilation integral:

\[I_{\mathbb{W}D}(\lambda_r) = \int_0^\infty D\, \sqrt{\mathbb{W}(D) \times D}\, e^{-\lambda_r D}\, dD\]

where $\mathbb{W}(D)$ is the piecewise Gunn-Kinzer/Beard rain fall speed, configured by fall_speed, at reference density. The kinematic viscosity ν is not baked into the table; 1/√ν is applied at runtime from T,P-dependent transport properties.

The full evaporation ventilation integral is assembled at runtime:

\[I_{\mathrm{evap}} = \frac{\mathbb{C}_{\mathrm{vent},1}}{\lambda_r^2} + \mathbb{C}_{\mathrm{vent},2}\, \frac{\mathrm{Sc}^{1/3}}{\sqrt{\nu}}\, I_{\mathbb{W}D}\]

where Sc = ν / Dᵛ is the Schmidt number and ν is the T,P-dependent kinematic viscosity. The ventilation coefficients $\mathbb{C}_{\mathrm{vent},1}$ and $\mathbb{C}_{\mathrm{vent},2}$ come from RainVentilation — the defaults are the standard values for falling drops tabulated by Pruppacher and Klett (2010). They deliberately do not enter this table, which stores only $I_{\mathbb{W}D}$; both are applied at runtime by rain_ventilation_integral. The constant term $\mathbb{C}_{\mathrm{vent},1} / λ_r²$ is the analytical result of $\mathbb{C}_{\mathrm{vent},1} ∫ D \exp(-λD) \, \mathrm{d}D$.

This integral appears in the PSD-integrated rain evaporation rate (Mason 1971, capacitance C = D/2 for a sphere, so 4πC = 2πD):

\[\frac{dq^r}{dt} \approx \frac{2 \pi N_0}{A + B}\,(S - 1)\, I_{\mathrm{evap}}\]

where A+B is the thermodynamic resistance factor.

source
Breeze.Microphysics.PredictedParticleProperties.RainVentilation — Type
RainVentilation(
    FT::DataType=Oceananigans.defaults.FloatType;
    constant_coefficient=0.78,
    reynolds_coefficient=0.32
) -> Breeze.Microphysics.PredictedParticleProperties.RainVentilation

Construct RainVentilation.

Keyword Arguments

  • constant_coefficient: $\mathbb{C}_{\mathrm{vent},1}$ [-], default 0.78
  • reynolds_coefficient: $\mathbb{C}_{\mathrm{vent},2}$ [-], default 0.32

Examples

using Breeze.Microphysics.PredictedParticleProperties: RainVentilationRainVentilation(Float64)# outputRainVentilation(ℂᵛᵉⁿᵗ₁=0.78, ℂᵛᵉⁿᵗ₂=0.32)
source
Breeze.Microphysics.PredictedParticleProperties.RainVentilation — Type
RainVentilation{FT}

Coefficients of the rain ventilation factor $f^{ve} = \mathbb{C}_{\mathrm{vent},1} + \mathbb{C}_{\mathrm{vent},2}\, \mathrm{Sc}^{1/3}\,\mathrm{Re}^{1/2}$, the classical form of Pruppacher and Klett (2010). These are P3's traditional f1r/f2r coefficients.

The ice side uses the same form with its own pair (0.65, 0.44), folded into the lookup tables at generation: the *_ventilation_constant / *_ventilation_reynolds fields of IceDeposition hold the scaled integrals, not the coefficients, so the ice pair is not configurable.

Consumed at runtime by rain_ventilation_integral, which assembles the analytical $\mathbb{C}_{\mathrm{vent},1}/(λ^r)^2$ term and the Reynolds-weighted term around the tabulated velocity-diameter integral. They deliberately do not enter that table, which stores only $I_{\mathbb{W}D}$.

See the constructor for the meaning and defaults of each coefficient.

source
Breeze.AtmosphereModels.prognostic_field_names — Method
prognostic_field_names(
    p3::PredictedParticlePropertiesMicrophysics
) -> Tuple{Vararg{Symbol}}

Return prognostic field names for the P3 scheme.

  • Cloud mass (always): ρqᶜˡ
  • Cloud number (only when aerosol::AerosolActivation is set): ρnᶜˡ
  • Rain: ρqʳ, ρnʳ
  • Ice (always): ρqⁱ, ρnⁱ, ρqᶠ, ρbᶠ, ρqʷⁱ
  • Vapor excess over liquid (only when vapor_excess = PrognosticVaporExcess()): ρδqᵛ⁺ˡ
  • Aerosol (only when aerosol::AerosolActivation sets prognostic): ρnᵃ
source
Breeze.Microphysics.PredictedParticleProperties.activated_number — Method
activated_number(
    mode::Breeze.Microphysics.PredictedParticleProperties.AerosolMode,
    aerosol::Breeze.Microphysics.PredictedParticleProperties.AerosolActivation,
    T,
    S
)

Compute the activated number [kg⁻¹] from a single lognormal aerosol mode at temperature T [K] and environmental supersaturation S [-].

Following Morrison and Grabowski (2007), the critical supersaturation for mode activation is

\[s_m = 2 \left(\frac{1}{\beta_{\text{act}}}\right)^{1/2} \left(\frac{A_{\text{act}}}{3 \, r_m}\right)^{3/2}\]

and the activated fraction is $N^a / 2 \, [1 - \text{erf}(u)]$ where $u = 2 \ln(s_m / S) / (4.242 \ln \sigma_g)$.

source
Breeze.Microphysics.PredictedParticleProperties.aerosol_activation_rate — Method
aerosol_activation_rate(
    aerosol::Breeze.Microphysics.PredictedParticleProperties.AerosolActivation,
    nᶜˡ,
    nᵃ,
    qᵛ,
    qᵛ⁺ˡ,
    T
) -> NamedTuple{(:ncnuc, :qcnuc), <:Tuple{Any, Any}}

Compute cloud droplet activation rates from the aerosol distribution. The supplied nᵃ limits activation to the remaining aerosol population; omitting it uses the full distribution.

Returns a named tuple (; ncnuc, qcnuc):

  • ncnuc: Cloud number activation rate [kg⁻¹ s⁻¹]
  • qcnuc: Cloud mass activation rate [kg/kg/s]

The equilibrium count $N_{\text{act}}(S)$ follows Morrison and Grabowski (2007). Capping the target by the available aerosol gives

\[n_{\text{nuc}} = \frac{\max(0,\; \min(N_{\text{act}}(S), n^{cl} + n^a) - n^{cl})} {\mathbb{C}_{\mathrm{form},4}}.\]

Each activated droplet consumes one aerosol from a prognostic reservoir, giving the density tendency $-ρ \, n_{\text{nuc}}$.

Mass follows as $q_{\text{nuc}} = n_{\text{nuc}} \times m_{\text{seed}}$ where $m_{\text{seed}} = (4\pi/3) \rho_w (\mathbb{C}_{\mathrm{form},2})^3$ is a droplet of the activated radius, 1 μm by default.

source
Breeze.Microphysics.PredictedParticleProperties.air_transport_properties — Method
air_transport_properties(
    T,
    P,
    constants
) -> NamedTuple{(:Dᵛ, :Kᵃ, :ν), <:Tuple{Any, Any, Any}}

Compute T,P-dependent air transport properties following Milbrandt et al. (2021).

Returns a named tuple (; Dᵛ, Kᵃ, ν):

  • Dᵛ: vapor diffusivity [m²/s], from 8.794e-5 × T^1.81 / P
  • Kᵃ: thermal conductivity of air [W/m/K], from 1414 × η
  • ν: kinematic viscosity [m²/s], from η × Rᵈ × T / P

where η = 1.496e-6 × T^1.5 / (T + 120) is the dynamic viscosity (Pa s) from Sutherland's law. It is written η rather than μ, which denotes the particle size distribution shape parameter throughout this module.

Arguments

  • T: Temperature [K]
  • P: Pressure [Pa]
  • constants: Thermodynamic constants supplying the dry-air gas constant used in the kinematic-viscosity calculation.

Reference values

At T = 273.15 K, P = 101325 Pa:

  • Dᵛ ≈ 2.23e-5 m²/s
  • Kᵃ ≈ 0.024 W/m/K
  • ν ≈ 1.33e-5 m²/s

Example

using Breezeusing Breeze.Microphysics.PredictedParticleProperties: air_transport_propertiesconstants = ThermodynamicConstants()properties = air_transport_properties(273.15, 101325.0, constants)map(x -> round(x, sigdigits=3), properties)# output(Dᵛ = 2.23e-5, Kᵃ = 0.0243, ν = 1.33e-5)
source
Breeze.Microphysics.PredictedParticleProperties.liu_daum_shape_parameter — Method
liu_daum_shape_parameter(Nᶜˡ, shape)

Diagnose the cloud droplet gamma PSD shape parameter μᶜˡ from the absolute number concentration Nᶜˡ [m⁻³] and the CloudShape shape:

\[\chi = \mathbb{C}_{cl,1} \, N^{cl} + \mathbb{C}_{cl,2}, \qquad \mu^{cl} = \mathrm{clamp}\!\left(\frac{1}{\chi^2} - 1,\; \mathbb{C}_{cl,3},\; \mathbb{C}_{cl,4}\right)\]

The relation is written for the absolute number density, so a specific droplet number [kg⁻¹] would first have to be multiplied by ρ. Nᶜˡ here is already the absolute density [m⁻³], so no ρ is required.

Every model path — construction-time diagnosis, diagnose_cloud_dsd, and the immersion_freezing_cloud_rate PSD correction — passes p3.cloud.shape, so a custom fit reaches all three.

Examples

using Breeze.Microphysics.PredictedParticleProperties: CloudShape,                                                       liu_daum_shape_parametershape = CloudShape(Float64)round(liu_daum_shape_parameter(100e6, shape), digits=1)  # continental default# output8.3
source
Breeze.Microphysics.PredictedParticleProperties.psd_correction_spherical_volume — Method
psd_correction_spherical_volume(mu)

Compute the analytically exact PSD correction factor for volume-dependent immersion freezing of spherical drops with a gamma size distribution.

For a gamma PSD N'(D) = N₀ D^μ exp(−λD), the Barklie-Gokhale (1959) freezing probability per drop scales with volume ∝ D³, so the mass freezing rate ∝ mass × volume ∝ D⁶. The PSD-integrated rate is therefore $M₆$, against $M₃²/M₀$ for the mean-mass approximation, where $M_k = ∫ D^k N'(D) \, dD$. Their ratio is:

\[C(\mu) = \frac{\Gamma(\mu + 7)\,\Gamma(\mu + 1)}{\Gamma(\mu + 4)^2}\]

Evaluated through the equivalent rational form (μ+6)(μ+5)(μ+4) / ((μ+3)(μ+2)(μ+1)) — exact, overflow-free, and free of the three loggamma calls the gamma form would cost at every grid point.

Exact values:

  • μ = 0: 720 × 1 / 36 = 20.0
  • μ = 2: 40320 × 2 / 14400 = 5.6
  • μ = 5: 11×10×9 / (8×7×6) ≈ 2.946
  • Monotonically decreasing with μ (narrower PSD → less enhancement)

Arguments

  • mu: Shape parameter μ of the gamma PSD [-]

Example

using Breeze.Microphysics.PredictedParticleProperties: psd_correction_spherical_volumepsd_correction_spherical_volume(0.0)# output20.0
source
Breeze.Microphysics.PredictedParticleProperties.read_lookup_tables — Method
read_lookup_tables(
    directory::AbstractString;
    FT::DataType=Oceananigans.defaults.FloatType,
    arch=CPU(),
    thermodynamic_constants=ThermodynamicConstants(FT),
    minimum_mass_mixing_ratio=1.0e-14,
    minimum_number_mixing_ratio=1.0e-16,
    precipitation_boundary_condition=nothing,
    negative_moisture_correction=SpeciesBorrowing(),
    aerosol=nothing,
    cloud=nothing,
    rain=nothing,
    process_rates=nothing,
    warm_rain_scheme=KhairoutdinovKogan2000()
)

Read the P3 lookup tables from their ASCII files and construct a complete PredictedParticlePropertiesMicrophysics with tabulated ice integrals.

Nothing is fetched here: directory must already hold the table file, and it is an error if it does not. The tables themselves are not part of the source tree — they are a lazy Pkg artifact (P3_lookup_tables in Breeze's Artifacts.toml, a tarball pinned by SHA-256), which PredictedParticlePropertiesMicrophysics resolves to a path with artifact"P3_lookup_tables" and passes here. Pkg downloads and caches it on first use.

Rain 1D tables (velocity, evaporation) are generated from Julia quadrature since they are not included in the ASCII table files.

Arguments

  • directory: Path to directory containing the ASCII table file (p3_lookupTable_1.dat-v6.9-2momI).

Keyword Arguments

  • FT: Float type (default Float64)
  • arch: Architecture for GPU transfer (default CPU())
  • thermodynamic_constants: Source of shared phase and dry-air properties.
  • cloud: CloudDroplets, or nothing for the default.
  • rain: RainDrops skeleton supplying the fall-speed and ventilation parameters, or nothing for the default. Its parameter containers are preserved through the startup quadrature: the fall-speed law is what the three rain tables are built from, and the ventilation coefficients survive into the materialized RainDrops for the runtime rates that assemble them.
source
Breeze.Microphysics.PredictedParticleProperties.tabulate_rain_from_quadrature — Function
tabulate_rain_from_quadrature(
    rain::Breeze.Microphysics.PredictedParticleProperties.RainDrops,
    arch=CPU(),
    FT::DataType=Oceananigans.defaults.FloatType;
    lambda_points::Int64=200,
    log_lambda_range=(FT(2.5), FT(5.5)),
    quadrature_points::Int64=128,
    floors=NumericalFloors(FT)
)

Materialize the three rain lookup tables of a RainDrops skeleton by integrating its RainFallSpeed law with Chebyshev-Gauss quadrature.

Rain 1D tables are not present in the published P3 ASCII files, so they are generated here at startup: the mass- and number-weighted terminal velocities and the velocity-diameter integral used by evaporation, each tabulated against log10(λʳ) over log_lambda_range.

All three evaluators receive the same rain.fall_speed, so a configured fall-speed law reaches every table. Only the three lookup placeholders are replaced; fall_speed and ventilation are carried through unchanged, keeping custom values alive from the constructor into the runtime rates.

Arguments

  • rain: the RainDrops skeleton whose lookup fields are still nothing
  • arch: architecture the tabulated arrays are placed on (default CPU())
  • FT: float type of the tables

Keyword Arguments

  • lambda_points: number of tabulated log10(λʳ) nodes (default 200)
  • log_lambda_range: tabulated log10(λʳ) range (default (2.5, 5.5))
  • quadrature_points: Chebyshev-Gauss points per integral (default 128)
  • floors: NumericalFloors, carried because tabulation runs before a scheme exists
source

MoistAirBuoyancies

Breeze.MoistAirBuoyancies.MoistAirBuoyancy — Method
MoistAirBuoyancy(
    grid;
    base_pressure=101325,
    reference_potential_temperature=288,
    standard_pressure=100000.0,
    thermodynamic_constants=ThermodynamicConstants(eltype(grid)),
    surface_pressure=nothing
)

Return a MoistAirBuoyancy formulation that can be provided as input to an Oceananigans.NonhydrostaticModel.

Required tracers

MoistAirBuoyancy requires tracers θ and qᵗ.

Example

using Breeze, Oceananigansgrid = RectilinearGrid(size=(1, 1, 8), extent=(1, 1, 3e3))buoyancy = MoistAirBuoyancy(grid)# outputMoistAirBuoyancy:├── reference_state: ReferenceState{Float64}(p₀=101325.0, θ₀=288.0, pˢᵗ=100000.0)└── thermodynamic_constants: ThermodynamicConstants{Float64}

To build a model with MoistAirBuoyancy, we include potential temperature and total specific humidity tracers θ and qᵗ to the model.

model = NonhydrostaticModel(grid; buoyancy, tracers = (:θ, :qᵗ))# outputNonhydrostaticModel{CPU, RectilinearGrid}(time = 0 seconds, iteration = 0)├── grid: 1×1×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×3 halo├── timestepper: RungeKutta3TimeStepper├── advection scheme:│   ├── momentum: Centered(order=2)│   ├── θ: Centered(order=2)│   └── qᵗ: Centered(order=2)├── tracers: (θ, qᵗ)├── closure: Nothing├── buoyancy: MoistAirBuoyancy with ĝ = NegativeZDirection()└── coriolis: Nothing
source

ParcelModels

Breeze.ParcelModels.ParcelDynamics — Type
ParcelDynamics(
    FT::DataType=Oceananigans.defaults.FloatType;
    vertical_velocity_formulation=PrescribedVerticalVelocity(),
    base_pressure=101325,
    standard_pressure=100000.0,
    surface_pressure=nothing
) -> ParcelDynamics{Nothing, Nothing, Nothing, Nothing, PrescribedVerticalVelocity}

Construct ParcelDynamics with default (uninitialized) state.

The environmental profiles and parcel state are set using set! after constructing the AtmosphereModel. The model's formulation selects liquid–ice potential temperature (the default) or static energy as the parcel's conserved thermodynamic variable.

source
Breeze.ParcelModels.ParcelDynamics — Type
struct ParcelDynamics{S, TS, D, P, U, FT}

Lagrangian parcel dynamics for AtmosphereModel.

Fields

  • state: parcel state (position, thermodynamics, microphysics)
  • timestepper: SSP RK3 timestepper with tendencies
  • density: environmental density field [kg/m³]
  • pressure: environmental pressure field [Pa]
  • base_pressure: pressure of the reference atmosphere at $z = 0$ [Pa]
  • standard_pressure: standard pressure for potential temperature [Pa]
source
Breeze.ParcelModels.ParcelInitialState — Type
mutable struct ParcelInitialState{FT, MP}
  • x::Any

  • y::Any

  • z::Any

  • w::Any

  • qᵗ::Any

  • ℰ::Any

  • μ::Any

Storage for the initial parcel prognostic state at the beginning of a time step. Used by SSP RK3 to combine the initial state with intermediate states.

source
Breeze.ParcelModels.ParcelModel — Type
ParcelModel

Type alias for AtmosphereModel{<:ParcelDynamics}.

A ParcelModel represents a Lagrangian adiabatic parcel that rises through a prescribed environmental atmosphere. The parcel is characterized by its position (x, y, z), thermodynamic state, and moisture content. The environmental profiles (temperature, pressure, density, velocities) are defined on a 1D vertical grid.

The parcel's motion is determined by interpolating environmental velocities to the parcel position, and its thermodynamic evolution follows adiabatic processes with optional microphysical interactions.

See also ParcelDynamics, AtmosphereModel.

source
Breeze.ParcelModels.ParcelState — Type
mutable struct ParcelState{FT, TH, MP}
  • x::Any

  • y::Any

  • z::Any

  • w::Any

  • ρ::Any

  • qᵗ::Any

  • ρqᵗ::Any

  • ℰ::Any

  • ρℰ::Any

  • 𝒰::Any

  • μ::Any

State of a Lagrangian air parcel with position, thermodynamic state, and microphysics.

The parcel model evolves specific quantities (qᵗ, ℰ) directly for exact conservation. Density-weighted forms (ρqᵗ, ρℰ) are also stored for consistency with the microphysics interface.

  • w: parcel vertical velocity [m/s], prognostic for PrognosticVerticalVelocity, zero for PrescribedVerticalVelocity
  • ρ: environmental density at parcel height [kg/m³], interpolated from background profile, used as the weight for stored prognostics. Microphysical rates use the parcel's own density, computed from density(𝒰, constants) using the ideal gas law applied to the parcel's thermodynamic state.
source
Breeze.ParcelModels.ParcelTimestepper — Type
struct ParcelTimestepper{GT, U0, FT}

SSP RK3 time-stepper for ParcelModel.

Stores tendencies, the initial state at the beginning of a time step, and the SSP RK3 stage coefficients.

Fields

  • G: tendencies for prognostic variables
  • U⁰: initial state storage (position, moisture, thermodynamics, microphysics)
  • α¹, α², α³: SSP RK3 stage coefficients (1, 1/4, 2/3)
source
Breeze.ParcelModels.PrescribedVerticalVelocity — Type
PrescribedVerticalVelocity

Singleton type for prescribed vertical velocity dynamics. The parcel moves following the prescribed environmental vertical velocity field w(z).

This is the default vertical velocity formulation: dz/dt = w_env(z).

source
Breeze.ParcelModels.PrognosticVerticalVelocity — Type
PrognosticVerticalVelocity

Singleton type for prognostic vertical velocity dynamics. The parcel has a prognostic vertical velocity driven by buoyancy, i.e., dz/dt = w and dw/dt = b, where b = -g (ρᵖ - ρᵉ) / ρᵉ is the net buoyancy from the density difference, including both the virtual temperature effect and condensate loading.

source
Breeze.ParcelModels.compute_parcel_tendencies! — Method
compute_parcel_tendencies!(
    model::AtmosphereModel{<:ParcelDynamics}
)

Compute tendencies for the parcel prognostic variables.

Position tendencies are interpolated from environmental velocity fields. Thermodynamic and moisture tendencies come from microphysical sources/sinks.

The parcel model evolves specific static energy or liquid–ice potential temperature and total water directly. These quantities are conserved when their tendencies vanish.

source
Breeze.ParcelModels.materialize_parcel_microphysics_prognostics — Method
materialize_parcel_microphysics_prognostics(
    FT,
    microphysics
) -> Union{Nothing, NamedTuple}

Create the parcel microphysics prognostic variables for the given microphysics scheme.

Returns nothing for microphysics schemes without explicit prognostic variables (e.g., Nothing, SaturationAdjustment), or a NamedTuple containing the prognostic density-weighted scalars for schemes with prognostic microphysics.

The prognostic variables use the same ρ-weighted names as the grid-based model (e.g., :ρqᶜˡ, :ρqʳ) from prognostic_field_names(microphysics).

All values start at zero. A scheme that carries a prognostic aerosol reservoir ρnᵃ holds a ρ-weighted count there, so its default is only meaningful once the parcel has an environmental density, which set! supplies through set_parcel_aerosol_number.

source
Breeze.ParcelModels.parcel_buoyancy — Method
parcel_buoyancy(state, dynamics, constants)

Compute the net buoyancy acceleration for a parcel.

The buoyancy is computed from the density difference between the parcel and environment:

\[B = -g (ρ_{parcel} - ρ_{env}) / ρ_{env}\]

Here, $ρ_{env}$ is the environmental density interpolated at the parcel height and $ρ_{parcel} = p / (Rᵐ T)$ is the total parcel density from the ideal gas law, where $Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ$ with $qᵈ = 1 - qᵛ - qˡ - qⁱ$. This formulation captures both the virtual temperature effect (from vapor content) and the condensate loading effect (condensate reduces $qᵈ$, reducing $Rᵐ$, increasing $ρ_{parcel}$) in a single term without double-counting.

source
Breeze.ParcelModels.ssp_rk3_parcel_substep! — Method
ssp_rk3_parcel_substep!(
    model::AtmosphereModel{<:ParcelDynamics},
    U⁰::Breeze.ParcelModels.ParcelInitialState,
    Δt,
    α
)

Apply an SSP RK3 substep with coefficient $α$:

\[u^{(m)} = (1 - α) u^{(0)} + α \left[u^{(m-1)} + Δt \, G^{(m-1)}\right]\]

where $u^{(0)}$ is the initial state, $u^{(m-1)}$ is the current state, and $G^{(m-1)}$ is the tendency at the current state.

The parcel model steps specific quantities (ℰ, qᵗ), where ℰ is static energy or liquid–ice potential temperature. Both are conserved when their tendencies vanish.

source

PotentialTemperatureFormulations

Breeze.PotentialTemperatureFormulations — Module
PotentialTemperatureFormulations

Submodule defining the liquid-ice potential temperature thermodynamic formulation for atmosphere models.

LiquidIcePotentialTemperatureFormulation uses liquid-ice potential temperature density ρθ as the prognostic thermodynamic variable.

source
Breeze.PotentialTemperatureFormulations.LiquidIcePotentialTemperatureFormulation — Type
struct LiquidIcePotentialTemperatureFormulation{F, T, S, E}

LiquidIcePotentialTemperatureFormulation uses liquid-ice potential temperature density ρθ as the prognostic thermodynamic variable.

The liquid-ice potential temperature is defined exactly from the enthalpy,

\[θˡⁱ = \frac{H}{ĉᵖ Π} , \qquad H = cᵖᵐ T - ℒˡ₀ qˡ - ℒⁱ₀ qⁱ , \qquad Π = \left( \frac{p}{pˢᵗ} \right)^κ ,\]

where $ĉᵖ = qᵈ cᵖᵈ + qᵗ cᵖᵛ$ is the vapor-equivalent heat capacity (the heat capacity the parcel would have if all of its water were vapor) and $ℒˡ₀$, $ℒⁱ₀$ are the latent heats extrapolated to absolute zero. With Kirchhoff's law $ℒ(T) = ℒ₀ + (cᵖᵛ - cˣ) T$ this is $θˡⁱ = [T - (ℒˡ(T) qˡ + ℒⁱ(T) qⁱ) / ĉᵖ] / Π$, and $θˡⁱ = T / Π$ in unsaturated air. The exponent $κ$ is chosen by exner_exponent:

Because $ĉᵖ Π$ depends on the composition only through $qᵗ$, any phase change at fixed $θˡⁱ$, pressure, and total water conserves the enthalpy exactly and releases the latent heat $ℒ(T)$. Expansion at fixed composition is made consistent with the first law by the source

\[ρ \frac{Rᵐ T - κ ĉᵖ Π θˡⁱ}{ĉᵖ Π} \frac{D \ln p}{Dt} ,\]

which the dynamics add to the $ρθ$ equation with $D \ln p / Dt ≈ - g ρ w / p$; it vanishes in unsaturated air with the default exponent. Energy sources $Q$ enter as $Q / (ĉᵖ Π)$.

Recovering temperature from θˡⁱ may require an iterative inversion, depending on the dynamics: with prognostic-density (compressible) dynamics, temperature solves the implicit relation cᵖᵐ T = ĉᵖ (ρRᵐT/pˢᵗ)^κ θ + ℒˡ₀ qˡ + ℒⁱ₀ qⁱ. The inversion is controlled by temperature_solver:

  • DefaultTemperatureSolver() (default): resolved at materialization to default_temperature_solver(dynamics) — nothing for anelastic dynamics (closed-form inversion) and NewtonSolver() for compressible dynamics.
  • NewtonSolver: tolerance-based Newton iteration.
  • FixedIterations: a fixed number of Newton steps with no convergence test, which unrolls to straight-line code (required for Reactant tracing and cheap reverse-mode differentiation).
  • nothing: the non-iterated closed-form inversion.
source
Breeze.PotentialTemperatureFormulations.LiquidIcePotentialTemperatureFormulation — Method
LiquidIcePotentialTemperatureFormulation(;
    temperature_solver=DefaultTemperatureSolver(),
    exner_exponent=VaporEquivalentExponent()
) -> LiquidIcePotentialTemperatureFormulation{Nothing, Nothing, Breeze.AtmosphereModels.DefaultTemperatureSolver, VaporEquivalentExponent}

Return a LiquidIcePotentialTemperatureFormulation with the given temperature_solver and Exner exponent exner_exponent, either VaporEquivalentExponent() (the default) or DryExponent(). The prognostic and diagnostic fields are materialized later in the model constructor.

using BreezeLiquidIcePotentialTemperatureFormulation(temperature_solver = FixedIterations(2))# outputLiquidIcePotentialTemperatureFormulation├── exner_exponent: VaporEquivalentExponent()└── temperature_solver: FixedIterations(2)
using BreezeLiquidIcePotentialTemperatureFormulation(exner_exponent=DryExponent())# outputLiquidIcePotentialTemperatureFormulation├── exner_exponent: DryExponent()└── temperature_solver: DefaultTemperatureSolver
source

RoundingTreatments

Breeze.RoundingTreatments — Module

Round-off treatments for the stage updates of Breeze's time steppers.

In reduced precision a stage update $u⁰ + δ$ rounds away any increment $δ$ smaller than half a unit in the last place (ulp) of $u⁰$. For slow tendencies (radiation, subsidence, slow microphysics) at small time steps the loss has the same sign at every step, so it is a bias rather than noise. The treatments here decide how that sum is rounded:

  • RoundToNearest: IEEE round-to-nearest, the default. Bitwise identical to Breeze's original stage updates and free.
  • StochasticRounding: rounds the sum up or down with probabilities that make it exact in expectation. Needs no extra storage; the random numbers come from a counter-based hash.

A new treatment subtypes AbstractRoundingTreatment and extends rounded_add. Deterministic compensated summation, which carries the lost part of each increment to the next step, would also need a persistent field per prognostic in the time stepper, zeroed by set! and saved by prognostic_state for checkpointing; that is left for later.

source
Breeze.RoundingTreatments.RoundToNearest — Type
struct RoundToNearest <: Breeze.RoundingTreatments.AbstractRoundingTreatment

IEEE round-to-nearest for the stage updates of a time stepper: Breeze's default. Stage updates are bitwise identical to those of a time stepper without a round-off treatment, at no extra cost. In single precision, increments smaller than half an ulp of the prognostic variable are lost; see StochasticRounding.

using BreezeRoundToNearest()# outputRoundToNearest()
source
Breeze.RoundingTreatments.StochasticRounding — Method
StochasticRounding(; seed=0) -> StochasticRounding{Nothing}

Stochastic rounding for the stage updates of a time stepper. Each stage update $u⁰ + δ$ is rounded to one of the two floats that bracket the exact sum, choosing the upper one with probability equal to the distance from the lower one divided by the gap between them. The expected value of every stage update is then the exact sum, so sub-ulp increments accumulate correctly on average, at the cost of a random walk of about $\text{ulp} \sqrt{N}$ after $N$ steps.

How the sum is rounded depends on the architecture: on CPUs a Float32 sum is computed in Float64 and truncated after adding random bits (WidenedSum); on GPUs, and for Float64, its rounding error is computed with TwoSum (TwoSum). Both give the same statistics; they differ only in speed.

The random numbers come from a counter-based hash of (seed, iteration, stage, field, i, j, k), so there is no random-number state: runs are deterministic, bitwise reproducible, independent of the architecture's thread scheduling, and restart reproducibly from a checkpoint (which stores the iteration). seed is reduced modulo $2³²$.

Stochastic rounding works in any floating-point precision. It is meant for Float32; in Float64 it is supported but rarely needed, and it adds ulp-sized noise to the solution.

using BreezeStochasticRounding(seed = 42)# outputStochasticRounding(seed=42)
source

SingleColumnMode

Breeze.SingleColumnMode — Module
SingleColumnMode

Run an AtmosphereModel as a single vertical column, or as a forest of independent columns advanced concurrently, on a grid with topology = (Flat, Flat, Bounded).

On such a grid every horizontal finite-difference operator returns zero (via Flat-topology dispatch in Oceananigans.Operators), so horizontal advection, diffusion, and pressure-gradient terms vanish and no halo information is exchanged in the horizontal. When the horizontal dimensions are given a size greater than one — e.g. with Oceananigans.Grids.ColumnEnsembleSize, which forces the horizontal halos to zero — the grid holds a horizontally independent forest of columns that can be stepped in a single kernel launch, with no coupling between them.

This module gathers the single-column-specific method extensions that would otherwise be scattered across the dynamics, closure, and model modules. It mirrors Oceananigans.HydrostaticFreeSurfaceModel's single-column mode. Per-column reference states live with the rest of the reference-state machinery in Breeze.Thermodynamics, since they build on the reference-state construction there.

source
Breeze.SingleColumnMode.SingleColumnGrid — Type
const SingleColumnGrid

A grid with topology = (Flat, Flat, Bounded) — a single vertical column, or (when the horizontal dimensions have size greater than one, e.g. via ColumnEnsembleSize) a forest of independent columns.

source

Solvers

Breeze.Solvers — Module
Solvers

Iterative solvers for the small nonlinear scalar problems that arise in Breeze's thermodynamics: equation-of-state temperature inversions, saturation adjustment, and dewpoint computation.

A "solver" is a lightweight, isbits description of an iteration's stopping rule that algorithms dispatch on:

  • NewtonSolver and SecantSolver iterate until a tolerance-based convergence criterion is met (or maxiter is reached).
  • FixedIterations performs an exact number of iterations with no convergence test at all. Because the trip count is fixed, the loop unrolls to straight-line code, which is required for Reactant tracing and cheap reverse-mode differentiation (a tolerance-based while loop traces to an XLA while op whose adjoint is pathological — see NumericalEarth/Breeze.jl#767).
  • nothing means "do not iterate": the algorithm returns its initial guess (typically a closed-form approximation).

The drivers newton_solve and secant_solve implement the iterations once, so every algorithm shares the same loop logic and the same solver vocabulary.

Tolerance conventions

The choice between reltol and abstol follows the natural scale of the residual:

  • Quantities bounded away from zero with a fixed precision target use an absolute tolerance. Every iteration on a temperature (the θˡⁱ→T inversion, saturation adjustment, the Boussinesq adjustment temperature) is solved to abstol = 1e-4 K — far below any physically or numerically meaningful temperature increment, yet reached in a handful of iterations by both Newton (quadratic) and secant (superlinear).
  • Quantities that range over orders of magnitude use a relative tolerance against an algorithm-supplied scale. The dewpoint solve iterates on a saturation-vapor-pressure residual (Pa), which spans roughly two decades over the atmospheric temperature range, so it uses reltol = 1e-4 against the vapor pressure; an absolute Pa tolerance would be meaningless across that range.
  • No tolerance is taken below the rounding noise of the residual. A residual such as θ(T) - θ₀ is a difference of numbers of size scale, so it is computed only to within a few units in the last place of scale: in Float32 near 300 K that is ~1e-4 K, the default abstol itself. secant_solve therefore stops once |r| ≤ 30 eps(scale) whatever the solver's tolerances, because a secant slope formed from residuals at the noise level is noise and can throw the iterate arbitrarily far.

Iteration caps reflect each method's convergence order and role: the quadratically-convergent Newton inversion caps at maxiter = 8, the superlinear secant temperature solves cap at maxiter = 20, and the dewpoint diagnostic caps at maxiter = 10.

source
Breeze.Solvers.FixedIterations — Type
struct FixedIterations

A solver that performs exactly iterations iterations with no convergence test.

The fixed trip count means the iteration unrolls to straight-line, branch-free code, making it the right choice for Reactant tracing and reverse-mode differentiation, where data-dependent while loops are pathological (NumericalEarth/Breeze.jl#767).

using BreezeFixedIterations(2)# outputFixedIterations(2)
source
Breeze.Solvers.NewtonSolver — Type
NewtonSolver(
    FT::DataType=Oceananigans.defaults.FloatType;
    reltol=0,
    abstol=0.0001,
    maxiter=8
) -> NewtonSolver

Return a NewtonSolver with relative tolerance reltol, absolute tolerance abstol, and iteration cap maxiter.

using BreezeNewtonSolver(maxiter=4)# outputNewtonSolver(reltol=0.0, abstol=0.0001, maxiter=4)
source
Breeze.Solvers.NewtonSolver — Type
struct NewtonSolver{FT}

A Newton iteration that terminates when the step size Δx satisfies |Δx| ≤ max(abstol, reltol * |x|), or after maxiter iterations.

source
Breeze.Solvers.SecantSolver — Type
SecantSolver(
    FT::DataType=Oceananigans.defaults.FloatType;
    reltol=0,
    abstol=0.0001,
    maxiter=20
) -> SecantSolver

Return a SecantSolver with relative tolerance reltol, absolute tolerance abstol, and iteration cap maxiter.

using BreezeSecantSolver(abstol=1e-4, maxiter=20)# outputSecantSolver(reltol=0.0, abstol=0.0001, maxiter=20)
source
Breeze.Solvers.SecantSolver — Type
struct SecantSolver{FT}

A secant iteration that terminates when the residual r satisfies |r| ≤ max(abstol, reltol * |scale|, 30 eps(scale)) — where scale is an algorithm-supplied magnitude for the residual and 30 eps(scale) is a floor at the residual's rounding noise — or after maxiter iterations.

source

StaticEnergyFormulations

Breeze.StaticEnergyFormulations — Module
StaticEnergyFormulations

Submodule defining the static energy thermodynamic formulation for atmosphere models.

StaticEnergyFormulation uses moist static energy density ρs as the prognostic thermodynamic variable. Moist static energy is a conserved quantity in adiabatic, frictionless flow that combines sensible heat, gravitational potential energy, and latent heat.

source
Breeze.StaticEnergyFormulations.StaticEnergyFormulation — Type
struct StaticEnergyFormulation{E, S}

StaticEnergyFormulation uses moist static energy density ρs as the prognostic thermodynamic variable.

Moist static energy is a conserved quantity in adiabatic, frictionless flow that combines sensible heat, gravitational potential energy, and latent heat:

\[s = cᵖᵐ T + g z - ℒˡ₀ qˡ - ℒⁱ₀ qⁱ\]

Here $ℒˡ₀ = ℒˡᵣ − (cᵖᵛ − cˡ) Tᵣ$ and $ℒⁱ₀ = ℒⁱᵣ − (cᵖᵛ − cⁱ) Tᵣ$ are the latent heats of condensation and deposition extrapolated to zero kelvin. Pairing the reference latent heats $ℒᵣ$ with $cᵖᵐ T$ would give incorrect phase-change heating.

The energy density equation includes a buoyancy flux term following Pauluis (2008).

source

TerrainFollowingDiscretization

Breeze.TerrainFollowingDiscretization — Module
TerrainFollowingDiscretization

Module implementing terrain-following vertical coordinates via the TerrainFollowingVerticalDiscretization (TFVD) grid type.

TFVD stores a uniform reference vertical coordinate $r$ and a formulation (e.g. LinearDecay or TwoLevelDecay) that defines the physical altitude

\[z(x, y, r) = r + h(x, y) \, b(r) ,\]

where $h(x, y)$ is the terrain and $b(r)$ is a decay basis satisfying $b(0) = 1$ and $b(z_\text{top}) = 0$.

Public API:

See docs/src/terrain_following_coordinates.md for the math, discrete operators, well-balancing reference state, and worked examples.

source
Breeze.TerrainFollowingDiscretization.LinearDecay — Type
struct LinearDecay{FT, H, SX, SY} <: Breeze.TerrainFollowingDiscretization.AbstractTerrainFormulation

Gal-Chen & Somerville (1975) terrain-following formulation: a single decay basis $b(r) = 1 - r/z_{top}$ that linearly attenuates the terrain from the surface to the model top.

source
Breeze.TerrainFollowingDiscretization.SlopeInsideInterpolation — Type
struct SlopeInsideInterpolation

Terrain pressure gradient stencil where the slope is multiplied inside the interpolation of $∂p'/∂r$:

\[\text{correction} = \overline{\overline{s \, \partial_r p'}^x}^z\]

The slope is evaluated at each (Center, Center, Face) stencil point before averaging to (Face, Center, Center).

source
Breeze.TerrainFollowingDiscretization.TerrainFollowingVerticalDiscretization — Method
TerrainFollowingVerticalDiscretization(
    r_faces;
    formulation=LinearDecay()
) -> TerrainFollowingVerticalDiscretization{<:Any, Nothing, Nothing, Nothing, LinearDecay{Nothing, Nothing, Nothing, Nothing}}

Skeleton constructor. r_faces is the reference (computational) r face specification — a range, vector, or function — exactly as for a static z grid. The terrain components inside formulation are filled later by materialize_terrain! once the horizontal grid exists.

source
Breeze.TerrainFollowingDiscretization.TerrainMetrics — Type
struct TerrainMetrics{H, SX, SY, FT, PG}

Pre-computed terrain derivative fields and model top height.

Fields

  • topography: 2D field storing $h(x, y)$ at (Center, Center)
  • ∂x_h: 2D field storing $\partial h / \partial x$ at (Face, Center)
  • ∂y_h: 2D field storing $\partial h / \partial y$ at (Center, Face)
  • z_top: Height of the model top (top of the reference coordinate)
  • pressure_gradient_stencil: Stencil type for the terrain-corrected horizontal pressure gradient (SlopeOutsideInterpolation or SlopeInsideInterpolation)
source
Breeze.TerrainFollowingDiscretization.TwoLevelDecay — Type
struct TwoLevelDecay{ZT, FT, H, SX, SY, B} <: Breeze.TerrainFollowingDiscretization.AbstractTerrainFormulation

Schär et al. (2002) "Smooth LEvel VErtical" (SLEVE) terrain-following formulation. Splits the terrain into a smoothed large-scale component $h_1$ (decay length large_scale_height) and the residual small-scale component $h_2$ (decay length small_scale_height). Each is attenuated with a hyperbolic-sine basis $b_n(r) = \sinh((z_{top}-r)/s_n) / \sinh(z_{top}/s_n)$, so the small-scale features decay quickly while the large-scale envelope is preserved aloft.

Constructed via the kwarg form TwoLevelDecay(; large_scale_height, small_scale_height).

source
Breeze.TerrainFollowingDiscretization.build_terrain_metrics — Method
build_terrain_metrics(grid, stencil) -> TerrainMetrics

Build a TerrainMetrics for a materialized TerrainFollowingVerticalDiscretization grid. On such grids the terrain slope used by the dynamics comes from the grid ∂z∂x operator (formulation decay), so this object only carries the pressure_gradient_stencil, z_top, and a representative terrain field.

source
Breeze.TerrainFollowingDiscretization.materialize_terrain! — Method
materialize_terrain!(grid, topography)

Fill the terrain components of a TerrainFollowingVerticalDiscretization grid in place from topography(x, y). Must be called after the grid is built (the horizontal nodes are needed to evaluate the topography). For TwoLevelDecay, the terrain is split into large- and small-scale parts by horizontal smoothing.

The topography is evaluated at the horizontal cell-centre nodes. Its arguments follow the grid's horizontal coordinates with Flat dimensions dropped, matching every other set! initialiser: topography(x, y) on a RectilinearGrid, topography(λ, φ) on a LatitudeLongitudeGrid, and e.g. topography(x) when y is Flat.

source

Thermodynamics

Breeze.Thermodynamics.ClausiusClapeyron — Type
struct ClausiusClapeyron

A saturation vapor pressure formulation based on the Clausius-Clapeyron relation.

The Clausius-Clapeyron equation describes how saturation vapor pressure varies with temperature based on thermodynamic principles. This formulation uses thermodynamic constants (latent heats, heat capacities, triple point values) to compute saturation vapor pressure analytically.

See saturation_vapor_pressure for the implementation details.

source
Breeze.Thermodynamics.CondensedPhase — Type
CondensedPhase(
    FT=Oceananigans.defaults.FloatType;
    reference_latent_heat,
    heat_capacity,
    density
)

Return CondensedPhase with specified parameters converted to FT.

Two examples of CondensedPhase are liquid and ice. When matter is converted from vapor to liquid, water molecules in the gas phase cluster together and slow down to form liquid with heat_capacity, The lost of molecular kinetic energy is called the reference_latent_heat.

Likewise, during deposition, water molecules in the gas phase cluster into ice crystals.

Arguments

  • FT: Float type to use (defaults to Oceananigans.defaults.FloatType)
  • reference_latent_heat: Difference between the internal energy of the gaseous phase at the energy_reference_temperature.
  • heat_capacity: Heat capacity of the phase of matter.
  • density: Reference mass density of the phase of matter [kg/m³].
source
Breeze.Thermodynamics.DryExponent — Type
struct DryExponent <: Breeze.Thermodynamics.AbstractExnerExponent

The dry-air Exner exponent $κᵈ = Rᵈ / cᵖᵈ$, the convention of most cloud models. The Exner function then depends on pressure alone. Unsaturated moist adiabatic motion changes $θˡⁱ$ slightly, which Breeze's dynamics correct with the same expansion-work source that corrects saturated motion.

Example

using BreezeDryExponent()# outputDryExponent()
source
Breeze.Thermodynamics.ExnerReferenceState — Type
ExnerReferenceState(
    grid,
    constants=ThermodynamicConstants(eltype(grid));
    base_pressure=101325,
    potential_temperature=288,
    reference_temperature=nothing,
    standard_pressure=100000.0,
    vapor_mass_fraction=nothing,
    surface_pressure=nothing
) -> ExnerReferenceState{<:Any, SP, SD, FP, FD, FE} where {SP<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), SD<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), FP<:(Field{Nothing, Nothing, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), FD<:(Field{Nothing, Nothing, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), FE<:(Field{Nothing, Nothing, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B})}

Construct an ExnerReferenceState by discrete Exner integration on grid.

Two modes are supported, controlled by which keyword is provided:

Isentropic (potential_temperature): Constant or horizontally-varying θ₀. Each column is built by Newton iteration on the discrete hydrostatic balance $(p_k - p_{k-1})/Δz_{face} + g(ρ_k + ρ_{k-1})/2 = 0$ so the substepper's slow vertical-momentum tendency vanishes to ulp on a rest atmosphere. The same column kernel handles both the 1D path (θ₀ constant or z-dependent) and the 3D path (θ₀(x, y, z)); vapor_mass_fraction is supported in both. When provided, the level-local moist gas constants $Rᵐ = (1-qᵛ)Rᵈ + qᵛRᵛ$, $cᵖᵐ = (1-qᵛ)cᵖᵈ + qᵛcᵖᵛ$ are used; the dry case is recovered exactly when $qᵛ ≡ 0$. The column is integrated with the vapor-equivalent Exner exponent $κᵐ = Rᵐ/cᵖᵐ$. A model evolving $θˡⁱ$ with DryExponent inverts the same $θ₀$ to a slightly different temperature; set_to_mean! recomputes the reference with the model's exponent.

Isothermal (reference_temperature): Constant T₀ (MPAS baroclinic wave convention). Uses the analytic isothermal solution: $p₀(z) = pˢ \exp(-g z / (Rᵈ T₀))$, $Π₀ = (p₀/pˢᵗ)^κ$, $ρ₀ = p₀/(Rᵈ T₀)$, $θ₀ = T₀/Π₀$. This matches MPAS initatmcases.F lines 813-817 exactly.

Arguments

  • grid: The grid
  • constants: Thermodynamic constants (default: ThermodynamicConstants(eltype(grid)))

Keyword Arguments

  • base_pressure: Pressure at $z = 0$ (default: 101325 Pa). This is a datum, not the pressure at the ground: on a domain whose bottom face sits above $z = 0$ it is reduced to that height before anchoring the column, so the reference profile passes through base_pressure at $z = 0$ regardless of where the domain starts.
  • potential_temperature: Constant value or function θᵣ(z) for isentropic reference (default: 288 K)
  • reference_temperature: Constant T₀ for isothermal reference (default: nothing). When provided, overrides potential_temperature.
  • standard_pressure: pˢᵗ for potential temperature definition (default: 1e5 Pa)
  • vapor_mass_fraction: Optional vapor mass fraction for a moist reference state. A number or function qᵛ(z) builds a 1D column; a multi-argument function qᵛ(x, y, z) (or qᵛ(φ, z) on a LatitudeLongitudeGrid) builds a 3D field.
source
Breeze.Thermodynamics.ExnerReferenceState — Type
ExnerReferenceState

A dry reference state built in Exner coordinates, ensuring that the discrete Exner hydrostatic balance

\[cᵖᵈ θᵣ^{face} \frac{π₀[k] - π₀[k-1]}{Δz} = -g\]

holds exactly at every interior z-face. This is essential for the Exner pressure acoustic substepping formulation, where the vertical pressure gradient is computed as $cᵖᵈ θᵥ ∂π'/∂z$ and the hydrostatic part must cancel to machine precision.

Unlike ReferenceState which builds pressure first and derives Exner, this type builds the Exner function π₀ first by discrete integration and then derives pressure and density from it. This matches CM1's approach where pi0 is the fundamental reference variable.

Fields

  • base_pressure: Reference pressure at z=0 (Pa). The datum, not a pressure at the ground: the two differ by $O(ρgh)$ whenever the ground is not at $z = 0$.
  • surface_pressure: Reference pressure at the bottom face of each column (Pa), as a 2D $(Center, Center, Nothing)$ field, obtained by reducing base_pressure to that height with moist_hydrostatic_pressure. Equal to base_pressure for the usual domain that starts at $z = 0$, and horizontally uniform on any height-coordinate grid, whose bottom face is a single level; genuinely column-dependent on a terrain-following grid, where it is the pressure at the terrain surface. This is the anchor every consumer of "pressure at the surface" actually wants, and the quantity that keeps the column integration, the cold start, and the diagnostic hydrostatic pressure consistent over terrain. A reference reset writes into this field in place, so consumers that captured it stay current — see surface_state_field.
  • surface_density: Reference density at the bottom face (kg/m³), the boundary value that the bottom ValueBoundaryCondition of density reads, or nothing for the 3D and terrain-following forms, whose density carries no bottom boundary value.
  • surface_potential_temperature: Reference potential temperature at z=0 (K)
  • standard_pressure: pˢᵗ for potential temperature definition (Pa)
  • pressure: Reference pressure field $p₀ = pˢᵗ π₀^{cᵖᵈ/Rᵈ}$ (derived from π₀)
  • density: Reference density field $ρ₀ = p₀/(Rᵈ T₀)$ (derived from π₀ and θᵣ)
  • exner_function: Reference Exner function π₀ (built by discrete integration)
source
Breeze.Thermodynamics.FlatauPolynomial — Type
FlatauPolynomial(
    FT=Oceananigans.defaults.FloatType;
    liquid_coefficients=(611.239921, 44.3987641, 1.42986287, 0.026484743, 0.000302950461, 2.06739458e-6, 6.40689451e-9, -9.52447341e-12, -9.76195544e-14),
    ice_coefficients=(611.147274, 50.316082, 1.88439774, 0.0420895665, 0.000615021634, 6.02588177e-6, 3.85852041e-8, 1.46898966e-10, 2.52751365e-13),
    reference_temperature=273.16,
    minimum_temperature_offset=80
) -> Breeze.Thermodynamics.FlatauPolynomial

Construct a FlatauPolynomial saturation vapor pressure formulation: the eighth-order polynomial fits of Flatau et al. (1992) to the saturation vapor pressure over planar liquid and ice surfaces,

\[pᵛ⁺(T) = \sum_{n=0}^{8} aₙ (T - Tᵣ)^n ,\]

with reference_temperature $Tᵣ = 273.16$ K and the relative-error-norm coefficient sets (their Tables 3 and 4), which are the fits in operational use in WRF-family microphysics. The temperature argument is clamped below at $Tᵣ -$ minimum_temperature_offset (80 K), the fits' stated range of validity.

Compared to the default integrated Clausius–Clapeyron formulation the polynomial agrees to within 0.2 % (liquid, 233–313 K) while replacing a ^ and an exp with a branch-free Horner chain — approximately 70× cheaper per call on CPU Float64 and free of the FP64 transcendental penalty on GPUs. See ClausiusClapeyron and TetensFormula for the alternative formulations.

Example

using Breeze.Thermodynamicsconstants = ThermodynamicConstants(; saturation_vapor_pressure = FlatauPolynomial())

References

  • Flatau, P. J., Walko, R. L. and Cotton, W. R. (1992). Polynomial fits to saturation vapor pressure. Journal of Applied Meteorology 31, 1507–1513.
source
Breeze.Thermodynamics.IdealGas — Type
struct IdealGas{FT}

A struct representing an ideal gas with molar mass and specific heat capacity.

Fields

  • molar_mass: Molar mass of the gas in kg/mol
  • heat_capacity: Specific heat capacity at constant pressure in J/(kg·K)

Examples

using Breezedry_air = IdealGas(molar_mass=0.02897, heat_capacity=1005)# outputIdealGas{Float64}(molar_mass=0.02897, heat_capacity=1005.0)
source
Breeze.Thermodynamics.MixedPhaseEquilibrium — Type
MixedPhaseEquilibrium(; freezing_temperature=273.15, homogeneous_ice_nucleation_temperature=233.15)

Represents a mixed-phase equilibrium where both liquid and ice condensates are considered. The liquid fraction varies linearly with temperature between the freezing temperature and the homogeneous ice nucleation temperature.

source
Breeze.Thermodynamics.MoistureMassFractions — Type
struct MoistureMassFractions{FT}

A struct representing the moisture mass fractions of a moist air parcel.

Fields

  • vapor: the mass fraction of vapor
  • liquid: the mass fraction of liquid
  • ice: the mass fraction of ice
source
Breeze.Thermodynamics.MoistureMassFractions — Method
MoistureMassFractions(
    r::Breeze.Thermodynamics.MoistureMixingRatio
) -> Breeze.Thermodynamics.MoistureMassFractions

Convert MoistureMixingRatio to MoistureMassFractions.

Mass fractions are defined as mass of constituent per total mass:

\[q = r / (1 + rᵗ)\]

where $rᵗ$ is the total mixing ratio.

source
Breeze.Thermodynamics.MoistureMixingRatio — Method
MoistureMixingRatio(
    q::Breeze.Thermodynamics.MoistureMassFractions
) -> Breeze.Thermodynamics.MoistureMixingRatio

Convert MoistureMassFractions to MoistureMixingRatio.

Mixing ratios are defined as mass of constituent per mass of dry air:

\[r = q / (1 - qᵗ) = q / qᵈ\]

where $qᵗ$ is the total specific moisture and $qᵈ = 1 - qᵗ$ is the dry air mass fraction.

source
Breeze.Thermodynamics.ReferenceState — Type
ReferenceState(
    grid,
    constants=ThermodynamicConstants(eltype(grid));
    base_pressure=101325,
    potential_temperature=288,
    standard_pressure=100000.0,
    discrete_hydrostatic_balance=false,
    vapor_mass_fraction=nothing,
    liquid_mass_fraction=nothing,
    ice_mass_fraction=nothing,
    surface_pressure=nothing
) -> ReferenceState{<:Any, SP, SD, STm, P, D, T, QV, QL, QI} where {SP<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), SD<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), STm<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), P<:(Field{LX, LY, Center, Nothing, G, I, D, T, B, Nothing} where {LX, LY, G, I, D, T, B}), D<:(Field{LX, LY, Center, Nothing, G, I, D, T, B, Nothing} where {LX, LY, G, I, D, T, B}), T<:(Field{LX, LY, Center, Nothing, G, I, D, T, B, Nothing} where {LX, LY, G, I, D, T, B}), QV<:(Oceananigans.Fields.ZeroField{T, 3} where T), QL<:(Oceananigans.Fields.ZeroField{T, 3} where T), QI<:(Oceananigans.Fields.ZeroField{T, 3} where T)}

Return a ReferenceState on grid, with ThermodynamicConstants constants that includes the hydrostatic reference pressure and reference density.

The reference state is initialized with a dry adiabatic temperature profile and the given moisture profiles (zero by default). The pressure and density are then computed by hydrostatic integration using the mixture gas constant $Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ$ and the ideal gas law $ρ = p / (Rᵐ T)$.

Arguments

  • grid: The grid.
  • constants :: ThermodynamicConstants: By default, ThermodynamicConstants(eltype(grid)).

Keyword arguments

  • base_pressure: Reference pressure at $z = 0$, the datum the hydrostatic profiles are anchored to rather than the pressure at the ground. By default, 101325.

  • potential_temperature: A constant value (default 288) or a function $θ(z)$ giving the potential temperature profile. When a constant is provided, closed-form adiabatic hydrostatic profiles are used. When a function is provided, the hydrostatic profiles are computed by numerical integration of $∂p/∂z = -g ρ$.

  • standard_pressure: Reference pressure for potential temperature ($pˢᵗ$). By default, 1e5.

  • discrete_hydrostatic_balance: If true, recompute the reference pressure from the reference density using discrete integration, so that ∂z(p_ref) + g * ℑz(ρ_ref) = 0 exactly at the discrete level. By default, false.

    Discrete vs continuous hydrostatic balance

    With discrete balance, reference subtraction becomes a no-op (the subtracted terms cancel to machine precision). For split-explicit compressible dynamics, continuous balance (default) is preferred: both the actual and reference states share similar $O(Δz^2)$ truncation errors that cancel in the perturbation PG, leaving only the tiny truncation error of the physical perturbation $∂(p - p_{ref})/∂z$.

  • vapor_mass_fraction: Initial qᵛ profile. Can be a Number, Function(z), or Field. Default: nothing (ZeroField).

  • liquid_mass_fraction: Initial qˡ profile. Default: nothing (ZeroField).

  • ice_mass_fraction: Initial qⁱ profile. Default: nothing (ZeroField).

Pass =0 to allocate an actual Field initialized to zero — required for later use with compute_reference_state! or set_to_mean!.

source
Breeze.Thermodynamics.TetensFormula — Type
TetensFormula(
    FT=Oceananigans.defaults.FloatType;
    reference_saturation_vapor_pressure=610,
    reference_temperature=273.15,
    liquid_coefficient=17.27,
    liquid_temperature_offset=35.85,
    ice_coefficient=21.875,
    ice_temperature_offset=7.65
) -> Breeze.Thermodynamics.TetensFormula

Construct a TetensFormula saturation vapor pressure formulation. Tetens's (1930) formula is an empirical relationship for the saturation vapor pressure,

\[pᵛ⁺(T) = pᵛ⁺ᵣ \exp \left( a \frac{T - Tᵣ}{T - δT} \right) ,\]

where $pᵛ⁺ᵣ$ is reference_saturation_vapor_pressure, $Tᵣ$ is reference_temperature, $a$ is an empirical coefficient, and $δT$ is a temperature offset.

See also the wikipedia article on "Tetens equation". Different coefficients are used for liquid water and ice surfaces. Default values for the liquid formula are from Monteith and Unsworth (2014), and default values for the ice formula are from Murray (1967):

Liquid water (T > 0°C):

  • liquid_coefficient: 17.27
  • liquid_temperature_offset: 35.85 K (corresponding to 237.3 K offset from 0°C)

Ice (T < 0°C):

  • ice_coefficient: 21.875
  • ice_temperature_offset: 7.65 K (corresponding to 265.5 K offset from 0°C)

References

  • Monteith, J. L. and Unsworth, M. H. (2014). Principles of Environmental Physics. 4th Edition (Academic Press).
  • Murray, F. W. (1967). On the computation of saturation vapor pressure. Journal of Applied Meteorology 6, 203–204.
  • Tetens, O. (1930). Über einige meteorologische Begriffe. Zeitschrift für Geophysik 6, 297–309.
  • Wikipedia: Tetens equation; https://en.wikipedia.org/wiki/Tetens_equation

Example

julia> using Breeze.Thermodynamicsjulia> tf = TetensFormula()TetensFormula{Float64}(pᵣ=610.0, Tᵣ=273.15, aˡ=17.27, δTˡ=35.85, aⁱ=21.875, δTⁱ=7.65)
source
Breeze.Thermodynamics.ThermodynamicConstants — Type
ThermodynamicConstants(
    FT=Oceananigans.defaults.FloatType;
    molar_gas_constant=8.314462618,
    gravitational_acceleration=9.81,
    energy_reference_temperature=273.15,
    triple_point_temperature=273.16,
    triple_point_pressure=611.657,
    dry_air_molar_mass=0.02897,
    dry_air_heat_capacity=1005,
    vapor_molar_mass=0.018015,
    vapor_heat_capacity=1850,
    liquid=liquid_water(FT),
    ice=water_ice(FT),
    saturation_vapor_pressure=ClausiusClapeyron()
) -> ThermodynamicConstants

Return ThermodynamicConstants with parameters that represent gaseous mixture of dry "air" and vapor, as well as condensed liquid and ice phases. The triple_point_temperature and triple_point_pressure may be combined with internal energy parameters for condensed phases to compute the vapor pressure at the boundary between vapor and a homogeneous sample of the condensed phase. The gravitational_acceleration parameter is included to compute ReferenceState quantities associated with hydrostatic balance. The liquid and ice phases contain their respective reference densities for use by microphysical parameterizations.

source
Breeze.Thermodynamics.VaporEquivalentExponent — Type
struct VaporEquivalentExponent <: Breeze.Thermodynamics.AbstractExnerExponent

The vapor-equivalent Exner exponent $κ̂ = R̂ / ĉᵖ$. Here $R̂ = qᵈ Rᵈ + qᵗ Rᵛ$ and $ĉᵖ = qᵈ cᵖᵈ + qᵗ cᵖᵛ$ are the gas constant and heat capacity the parcel would have if all of its water were vapor (see vapor_equivalent_gas_constant and vapor_equivalent_heat_capacity). With this exponent $θˡⁱ = T / Π̂$ in unsaturated air, and dry or moist unsaturated adiabatic motion conserves $θˡⁱ$ exactly. This is the default.

Example

using BreezeVaporEquivalentExponent()# outputVaporEquivalentExponent()
source
Breeze.Thermodynamics.WarmPhaseEquilibrium — Type
WarmPhaseEquilibrium() -> WarmPhaseEquilibrium

Represents a warm-phase equilibrium where only liquid water condensate is considered. The equilibrated surface is always a planar liquid surface.

source
Breeze.Thermodynamics.adiabatic_hydrostatic_density — Method
adiabatic_hydrostatic_density(z, p₀, θ₀, pˢᵗ, constants)

Compute the reference density at height z that associated with the reference pressure p₀, potential temperature θ₀, and standard pressure pˢᵗ. The reference density is defined as the density of dry air at the reference pressure and temperature.

source
Breeze.Thermodynamics.adiabatic_hydrostatic_pressure — Method
adiabatic_hydrostatic_pressure(z, p₀, θ₀, pˢᵗ, constants)

Compute the reference pressure at height z that associated with the reference pressure p₀, potential temperature θ₀, and standard pressure pˢᵗ. The reference pressure is defined as the pressure of dry air at the reference pressure and temperature.

source
Breeze.Thermodynamics.adjustment_saturation_specific_humidity — Method
adjustment_saturation_specific_humidity(
    T,
    pᵣ,
    qᵗ,
    constants,
    surface
)

Compute the saturation specific humidity $qᵛ⁺$ for use in saturation adjustment, assuming saturated conditions where condensate is present.

This function always uses the saturated formula (equation 37 in paper by Pressel et al. 2015):

\[qᵛ⁺ = ϵᵈᵛ (1 - qᵗ) \frac{pᵛ⁺}{pᵣ - pᵛ⁺}\]

where $ϵᵈᵛ = Rᵈ / Rᵛ ≈ 0.622$.

Unlike equilibrium_saturation_specific_humidity, this function does not check whether the air is actually saturated. It is intended for use within the saturation adjustment iteration where we assume saturated conditions throughout.

source
Breeze.Thermodynamics.air_pressure — Method
air_pressure(
    𝒰::Breeze.Thermodynamics.AbstractReferencePressureState,
    constants
)

Return the air pressure of the thermodynamic state 𝒰, in Pa.

States closed on a reference pressure — LiquidIcePotentialTemperatureState and StaticEnergyState — carry it directly. LiquidIceDensityState is closed on the density instead, so its pressure is diagnosed from the ideal gas law, p = ρ Rᵐ T.

source
Breeze.Thermodynamics.compute_hydrostatic_reference! — Method
compute_hydrostatic_reference!(
    ref::ReferenceState,
    constants
)

Compute the hydrostatic reference pressure and density profiles from the temperature and moisture mass fraction profiles stored in ref.

The integration uses the mixture gas constant Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ (where qᵈ = 1 - qᵛ - qˡ - qⁱ) and the ideal gas law ρ = p / (Rᵐ T).

source
Breeze.Thermodynamics.compute_reference_state! — Method
compute_reference_state!(
    ref::ReferenceState,
    T̄,
    q̄ᵛ,
    q̄ˡ,
    q̄ⁱ,
    constants
)

Recompute the reference pressure and density profiles by setting the reference temperature to T̄ and moisture mass fractions to q̄ᵛ, q̄ˡ, q̄ⁱ, then integrating the hydrostatic equation using the mixture gas constant Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ and ideal gas law ρ = p / (Rᵐ T).

T̄, q̄ᵛ, q̄ˡ, q̄ⁱ can be Numbers, Function(z)s, or Fields.

This function is useful for:

  • Initialization: setting the reference state to match a non-constant-θ initial condition
  • Runtime: calling from a callback to keep the reference state close to the evolving mean state
source
Breeze.Thermodynamics.dewpoint_temperature — Method
dewpoint_temperature(pᵛ, T, constants, surface, solver)

Compute the dewpoint temperature $T⁺$ given the vapor pressure pᵛ, actual temperature T, thermodynamic constants, and condensation surface.

The dewpoint temperature is defined as the temperature at which the saturation vapor pressure equals the actual vapor pressure:

\[pᵛ⁺(T⁺) = pᵛ\]

This implicit equation is solved using secant iteration, which works with any saturation vapor pressure formulation.

If the air is saturated or supersaturated ($pᵛ ≥ pᵛ⁺(T)$), the dewpoint equals the actual temperature and T is returned.

Arguments

  • pᵛ: Vapor pressure (Pa)

  • T: Actual temperature (K), used as upper bound and first guess

  • constants: ThermodynamicConstants

  • surface: Surface type for saturation vapor pressure calculation

  • solver: Iterative solver controlling the secant iteration; the convergence criterion compares the vapor pressure residual against pᵛ. When omitted, defaults to SecantSolver(reltol=1e-4, abstol=0, maxiter=10).

source
Breeze.Thermodynamics.equilibrated_surface — Function
equilibrated_surface(phase_equilibrium::AbstractPhaseEquilibrium, T)

Return the appropriate surface type for computing saturation vapor pressure given the phase equilibrium model and temperature T.

source
Breeze.Thermodynamics.equilibrium_saturation_specific_humidity — Method
equilibrium_saturation_specific_humidity(
    T,
    p,
    qᵗ,
    constants,
    surface
)

Compute the equilibrium saturation specific humidity $qᵛ⁺$ for air at temperature T, reference pressure p, and total specific moisture qᵗ, over a given surface. The function returns the correct saturation specific humidity in both saturated and unsaturated conditions:

  • In saturated conditions ($qᵗ ≥ qᵛ⁺$), condensate is present and $qᵛ = qᵛ⁺$. The dry-air mass fraction is fixed by $qᵗ$ (since $qᵈ = 1 - qᵗ$), and the equation of state can be solved in closed form or $qᵛ⁺$, yielding equation (37) of Pressel et al. (2015):

    \[qᵛ⁺ = \frac{ϵᵈᵛ \, (1 - qᵗ) \, pᵛ⁺(T)}{p - pᵛ⁺(T)} ,\]

    where $ϵᵈᵛ ≡ Rᵈ / Rᵛ ≈ 0.622$.

  • In unsaturated conditions ($qᵗ < qᵛ⁺$), all moisture is vapor and $qᵛ = qᵗ$. The density is then $ρ = p / (Rᵐ T)$ with mixture gas constant $Rᵐ = (1 - qᵗ) Rᵈ + qᵗ Rᵛ$, and

    \[qᵛ⁺ = \frac{pᵛ⁺(T)}{ρ \, Rᵛ \, T} .\]

The function selects the branch by computing the unsaturated $qᵛ⁺$ and comparing with qᵗ. See also saturation_total_specific_moisture, which is the special case $qᵗ = qᵛ⁺$, and the Atmosphere Thermodynamics section of the documentation for a derivation.

source
Breeze.Thermodynamics.ice_latent_heat — Method
ice_latent_heat(T, constants::ThermodynamicConstants)

Return the latent heat of sublimation (vapor → ice) at temperature T.

The latent heat varies linearly with temperature:

\[ℒⁱ(T) = ℒⁱᵣ + (cᵖᵛ - cⁱ)(T - Tᵣ)\]

where $ℒⁱᵣ$ is the reference latent heat at the energy reference temperature $Tᵣ$, $cᵖᵛ$ is the heat capacity of vapor, and $cⁱ$ is the heat capacity of ice.

source
Breeze.Thermodynamics.liquid_latent_heat — Method
liquid_latent_heat(T, constants::ThermodynamicConstants)

Return the latent heat of vaporization (vapor → liquid) at temperature T.

The latent heat varies linearly with temperature:

\[ℒˡ(T) = ℒˡᵣ + (cᵖᵛ - cˡ)(T - Tᵣ)\]

where $ℒˡᵣ$ is the reference latent heat at the energy reference temperature $Tᵣ$, $cᵖᵛ$ is the heat capacity of vapor, and $cˡ$ is the heat capacity of liquid water.

source
Breeze.Thermodynamics.mixture_gas_constant — Method
mixture_gas_constant(
    q::Breeze.Thermodynamics.MoistureMassFractions,
    constants::ThermodynamicConstants
)

Return the gas constant of moist air mixture [in J/(kg K)] given the specific humidity q and thermodynamic parameters constants.

The mixture gas constant is calculated as a weighted average of the dry air and water vapor gas constants:

\[Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ ,\]

where:

  • Rᵈ is the dry air gas constant,
  • Rᵛ is the water vapor gas constant,
  • qᵈ is the mass fraction of dry air, and
  • qᵛ is the mass fraction of water vapor.

Arguments

  • q: the moisture mass fractions (vapor, liquid, and ice)
  • constants: ThermodynamicConstants instance containing gas constants
source
Breeze.Thermodynamics.mixture_heat_capacity — Method
mixture_heat_capacity(
    q::Breeze.Thermodynamics.MoistureMassFractions,
    constants::ThermodynamicConstants
)

Compute the heat capacity of a mixture of dry air, vapor, liquid, and ice, where the mass fractions of vapor, liquid, and ice are given by q. The heat capacity of moist air is the weighted sum of its constituents:

\[cᵖᵐ = qᵈ cᵖᵈ + qᵛ cᵖᵛ + qˡ cˡ + qⁱ cⁱ ,\]

where qᵛ = q.vapor, qˡ = q.liquid, qⁱ = q.ice are the mass fractions of vapor, liquid, and ice constituents, respectively, and qᵈ = 1 - qᵛ - qˡ - qⁱ is the mass fraction of dry air. The heat capacities cᵖᵈ, cᵖᵛ, cˡ, cⁱ are the heat capacities of dry air, vapor, liquid, and ice at constant pressure, respectively. The liquid and ice phases are assumed to be incompressible.

source
Breeze.Thermodynamics.potential_temperature_from_temperature — Function
potential_temperature_from_temperature(
    T,
    p,
    pˢᵗ,
    constants,
    q::Breeze.Thermodynamics.MoistureMassFractions,
    κ̂=VaporEquivalentExponent()
)

Compute liquid-ice potential temperature from temperature and pressure, $θˡⁱ = (cᵖᵐ T - ℒˡ₀ qˡ - ℒⁱ₀ qⁱ) / (ĉᵖ Π)$.

Arguments

  • T: Temperature [K]
  • p: Pressure [Pa]
  • constants: Thermodynamic constants

Additional Arguments

  • pˢᵗ: Standard pressure for potential temperature definition [Pa]
  • q: Vapor specific humidity [kg/kg] or MoistureMassFractions containing the vapor, total liquid (cloud + rain), and total ice (cloud + snow) mass fractions. Defaults to dry air.
  • κ̂: The Exner exponent, VaporEquivalentExponent (default) or DryExponent.
source
Breeze.Thermodynamics.pressure_balanced_density — Method
pressure_balanced_density(
    ρ_background,
    θ_background,
    θ_initial
)

Return the density that keeps pressure unchanged when applying a potential-temperature perturbation at fixed composition.

pressure_balanced_density(ρ_background, θ_background, θ_initial) applies the dry-air / vapor-only relation, for which holding $ρ θ$ fixed avoids seeding an acoustic pressure perturbation.

For fixed-composition states with nonzero liquid or ice condensate, use pressure_balanced_density(ρ_background, θ_background, θ_initial, q, pᵣ, pˢᵗ, constants) instead. The condensate-aware method evaluates the full liquid-ice potential-temperature equation of state before balancing density.

Examples

using Breeze.Thermodynamics: pressure_balanced_densityρ_background = 1.0θ_background = 300.0θ_initial = 303.0pressure_balanced_density(ρ_background, θ_background, θ_initial)# output0.9900990099009901
source
Breeze.Thermodynamics.psychrometric_correction — Method
psychrometric_correction(ℒ, qᵛ⁺, cᵖ, Rᵛ, T)

Return the psychrometric correction $ξ$, the factor by which latent heating reduces the supersaturation available to drive a phase change,

\[ξ = 1 + \frac{ℒ^2 q^{v+}}{cᵖ Rᵛ T^2}\]

with ℒ the latent heat of the phase being formed, qᵛ⁺ the saturation mass fraction against it, and cᵖ the heat capacity the caller's energy budget is written with. An effective relaxation timescale is ξ τ, and an effective supersaturation excess is (qᵛ - qᵛ⁺) / ξ.

Microphysics.thermodynamic_adjustment_factor follows the constraint the thermodynamic state is closed on. At fixed pressure it is this form with $cᵖ = cᵖᵐ$, less the $qᵛ⁺ Rᵛ / Rᵐ$ by which the vapor lost to condensate lowers $qᵛ⁺$. At fixed density it differentiates the state's θ–density relation for the heating response and keeps the ideal-gas $-1/T$ term of $dqᵛ⁺/dT$. The form here matches the convention of the P3 scheme.

source
Breeze.Thermodynamics.relative_humidity — Function
relative_humidity(
    T,
    ρ,
    qᵛ,
    constants,
    surface=PlanarLiquidSurface()
)

Compute the relative humidity as the ratio of vapor pressure to saturation vapor pressure:

\[ℋ = pᵛ / pᵛ⁺ = qᵛ / qᵛ⁺\]

source
Breeze.Thermodynamics.saturation_specific_humidity — Method
saturation_specific_humidity(T, ρ, constants, surface)

Compute the saturation specific humidity for a gas at temperature T, total density ρ, constantsdynamics, and over surface via:

\[qᵛ⁺ = pᵛ⁺ / (ρ Rᵛ T) ,\]

where $pᵛ⁺$ is the saturation_vapor_pressure over surface, $ρ$ is total density, and $Rᵛ$ is the specific gas constant for water vapor.

Examples

First we compute the saturation specific humidity over a liquid surface:

using Breezeusing Breeze.Thermodynamics: PlanarLiquidSurface, PlanarIceSurface, PlanarMixedPhaseSurfaceconstants = ThermodynamicConstants()T = 288.0 # Room temperature (K)p = 101325.0 # Mean sea-level pressureRᵈ = Breeze.Thermodynamics.dry_air_gas_constant(constants)q = zero(Breeze.Thermodynamics.MoistureMassFractions{Float64})ρ = Breeze.Thermodynamics.density(T, p, q, constants)qᵛ⁺ˡ = Breeze.Thermodynamics.saturation_specific_humidity(T, ρ, constants, PlanarLiquidSurface())# output0.010359995391195264

Note, this is slightly smaller than the saturation specific humidity over an ice surface:

julia> qᵛ⁺ˡ = Breeze.Thermodynamics.saturation_specific_humidity(T, ρ, constants, PlanarIceSurface())0.011945100768555072

If a medium contains a mixture of 40% water and 60% ice that has (somehow) acquired thermodynamic equilibrium, we can compute the saturation specific humidity over the mixed phase surface,

mixed_surface = PlanarMixedPhaseSurface(0.4)qᵛ⁺ᵐ = Breeze.Thermodynamics.saturation_specific_humidity(T, ρ, constants, mixed_surface)# output0.01128386068542303
source
Breeze.Thermodynamics.saturation_vapor_pressure — Method
saturation_vapor_pressure(
    T,
    constants::Breeze.Thermodynamics.ClausiusClapeyronThermodynamicConstants,
    surface
)

Compute the saturation vapor pressure $pᵛ⁺$ over a surface labeled $β$ (for example, a planar liquid surface, or curved ice surface) using the Clausius-Clapeyron relation,

\[𝖽pᵛ⁺ / 𝖽T = pᵛ⁺ ℒᵝ(T) / (Rᵛ T^2) ,\]

where the temperature-dependent latent heat of the surface is $ℒᵝ(T)$.

Using a model for the latent heat that is linear in temperature, eg

\[ℒᵝ = ℒᵝ₀ + Δcᵝ T,\]

where $ℒᵝ₀ ≡ ℒᵝ(T=0)$ is the latent heat at absolute zero and $Δcᵝ ≡ cᵖᵛ - cᵝ$ is the constant difference between the vapor specific heat and the specific heat of phase $β$.

Note that we typically parameterize the latent heat in terms of a reference temperature $T = Tᵣ$ that is well above absolute zero. In that case, the latent heat is written

\[ℒᵝ = ℒᵝᵣ + Δcᵝ (T - Tᵣ) \qquad \text{and} \qquad ℒᵝ₀ = ℒᵝᵣ - Δcᵝ Tᵣ .\]

Integrating the Clausius-Clapeyron relation with a temperature-linear latent heat model, from the triple point pressure and temperature $(pᵗʳ, Tᵗʳ)$ to pressure $pᵛ⁺$ and temperature $T$, we obtain

\[\log(pᵛ⁺ / pᵗʳ) = - ℒᵝ₀ / (Rᵛ T) + ℒᵝ₀ / (Rᵛ Tᵗʳ) + (Δcᵝ / Rᵛ) \log(T / Tᵗʳ) ,\]

which then becomes

\[pᵛ⁺(T) = pᵗʳ (T / Tᵗʳ)^{Δcᵝ / Rᵛ} \exp \left [ (1/Tᵗʳ - 1/T) ℒᵝ₀ / Rᵛ \right ] .\]

Note

Any reference values for pressure and temperature can be used in principle. The advantage of using reference values at the triple point is that the same values can then be used for both condensation (vapor → liquid) and deposition (vapor → ice).

source
Breeze.Thermodynamics.saturation_vapor_pressure — Method
saturation_vapor_pressure(
    T,
    constants::Breeze.Thermodynamics.TetensFormulaThermodynamicConstants,
    ::PlanarIceSurface
)

Compute the saturation vapor pressure over a planar ice surface using Tetens' empirical formula with ice coefficients from Murray (1967):

\[pᵛ⁺(T) = pᵛ⁺ᵣ \exp \left( aⁱ \frac{T - Tᵣ}{T - δTⁱ} \right)\]

References

  • Murray, F. W. (1967). On the computation of saturation vapor pressure. Journal of Applied Meteorology 6, 203–204.
  • Tetens, O. (1930). Über einige meteorologische Begriffe. Zeitschrift für Geophysik 6, 297–309.
source
Breeze.Thermodynamics.supersaturation — Method
supersaturation(
    T,
    ρ,
    q::Breeze.Thermodynamics.MoistureMassFractions,
    constants,
    surface
)

Compute the supersaturation $𝒮 = pᵛ/pᵛ⁺ - 1$ over a given surface.

  • $𝒮 < 0$ indicates subsaturation (evaporation conditions)
  • $𝒮 = 0$ indicates saturation (equilibrium)
  • $𝒮 > 0$ indicates supersaturation (condensation conditions)

Arguments

  • T: Temperature
  • ρ: Total air density
  • q: MoistureMassFractions containing vapor, liquid, and ice mass fractions
  • constants: ThermodynamicConstants
  • surface: Surface type (e.g., PlanarLiquidSurface(), PlanarIceSurface())
source
Breeze.Thermodynamics.surface_density — Method
surface_density(p₀, θ₀, pˢᵗ, constants)

Compute the surface air density from surface pressure p₀, potential temperature θ₀, standard pressure pˢᵗ, and thermodynamic constants using the ideal gas law for dry air.

The temperature is computed from potential temperature using the Exner function: T₀ = Π₀ * θ₀ where Π₀ = (p₀ / pˢᵗ)^(Rᵈ/cᵖᵈ).

source
Breeze.Thermodynamics.surface_density — Method
surface_density(p₀, T₀, constants)

Compute the surface air density from surface pressure p₀, surface temperature T₀, and thermodynamic constants using the ideal gas law for dry air.

source
Breeze.Thermodynamics.temperature_from_potential_temperature — Function
temperature_from_potential_temperature(
    θ,
    p,
    pˢᵗ,
    constants,
    q::Breeze.Thermodynamics.MoistureMassFractions,
    κ̂=VaporEquivalentExponent()
)

Compute temperature from liquid-ice potential temperature and pressure, $T = (ĉᵖ Π θˡⁱ + ℒˡ₀ qˡ + ℒⁱ₀ qⁱ) / cᵖᵐ$.

Arguments

  • θ: Potential temperature [K]
  • p: Pressure [Pa]
  • constants: Thermodynamic constants

Additional Arguments

  • pˢᵗ: Standard pressure for potential temperature definition [Pa]
  • q: Vapor specific humidity [kg/kg] or MoistureMassFractions containing the vapor, total liquid (cloud + rain), and total ice (cloud + snow) mass fractions. Defaults to dry air.
  • κ̂: The Exner exponent, VaporEquivalentExponent (default) or DryExponent.
source

TimeSteppers

Breeze.TimeSteppers — Module

TimeSteppers module for Breeze.jl

Provides time stepping schemes for AtmosphereModel, including:

  • SSPRungeKutta3: Standard SSP RK3 scheme for explicit time stepping
  • AcousticRungeKutta3: Wicker-Skamarock RK3 with acoustic substepping for compressible dynamics
source
Breeze.TimeSteppers.AcousticRungeKutta3 — Type
struct AcousticRungeKutta3{FT, U0, TG, TI, AS, R} <: Oceananigans.TimeSteppers.AbstractTimeStepper

Wicker–Skamarock third-order Runge–Kutta time stepper with linearized acoustic substepping for fully compressible dynamics. Stage fractions $β = (1/3, 1/2, 1)$. Each stage:

  1. Re-evaluates slow tendencies (advection + Coriolis + closure + forcing only — PGF and buoyancy are handled inside the substep loop in linearized form).
  2. Runs an inner substep loop that evolves linearized acoustic perturbations from the RK stage-entry state, initialized with a rewind term so every stage still advances from the outer-step-start prognostic state.

The acoustic substep loop is in acoustic_rk3_substep_loop!; see AcousticSubstepper for the substepper's storage and parameters.

Fields

  • β₁, β₂, β₃: Stage fractions (1/3, 1/2, 1).
  • U⁰: Storage for state at the beginning of the outer time-step.
  • Gⁿ: Slow-tendency fields, recomputed each stage.
  • implicit_solver: Optional solver for the vertically-implicit pieces — closure diffusion and the adaptive-implicit vertical-advection remainder.
  • substepper: AcousticSubstepper for the linearized acoustic substep loop.
  • rounding: Round-off treatment of the final stage's update, RoundToNearest or StochasticRounding.

References

Wicker, L. J. & Skamarock, W. C. (2002). Time-splitting methods for elastic models using forward time schemes. MWR 130, 2088–2097.

source
Breeze.TimeSteppers.AcousticRungeKutta3 — Method
AcousticRungeKutta3(
    grid,
    prognostic_fields;
    dynamics,
    implicit_solver::TI=nothing,
    cache_advecting_state=false,
    Gⁿ::TG=map(similar, prognostic_fields),
    U⁰::U0=map(similar, prognostic_fields),
    rounding=RoundToNearest()
) where {TI, TG, U0}

Construct an AcousticRungeKutta3 time stepper for fully compressible dynamics.

Gⁿ and U⁰ may be supplied to alias another stepper's tendency storage instead of allocating fresh fields (used by the native-stepper adiabatic-balance twin).

rounding sets the round-off treatment of the step's final update (default: RoundToNearest). Every Wicker–Skamarock stage restarts from $Uⁿ$, so only the third stage's rounding reaches $Uⁿ⁺¹$: with StochasticRounding, the recovery of the acoustic prognostics from their stage-entry values plus the accumulated perturbations, and the update $u⁰ + Δt G$ of the other scalars, are rounded stochastically in the third stage. The perturbations themselves, the first two stages, and the vertically-implicit solves stay round-to-nearest.

source
Breeze.TimeSteppers.SSPRungeKutta3 — Type
struct SSPRungeKutta3{FT, U0, TG, TI, R} <: Oceananigans.TimeSteppers.AbstractTimeStepper

A strong stability preserving (SSP) third-order Runge-Kutta time stepper.

This time stepper uses the classic SSP RK3 scheme (Shu-Osher 2006 form):

\[\begin{align*} u^{(1)} &= u^{(0)} + Δt \, G(u^{(0)}) \\ u^{(2)} &= \frac{3}{4} u^{(0)} + \frac{1}{4} u^{(1)} + \frac{1}{4} Δt \, G(u^{(1)}) \\ u^{(3)} &= \frac{1}{3} u^{(0)} + \frac{2}{3} u^{(2)} + \frac{2}{3} Δt \, G(u^{(2)}) \end{align*}\]

where $G$ above is the right-hand-side, e.g., $\partial_t u = G(u)$.

Each stage can be written in the form:

\[u^{(m)} = (1 - α) u^{(0)} + α \left[u^{(m-1)} + Δt \, G(u^{(m-1)}) \right]\]

with $α = 1, 1/4, 2/3$ for stages 1, 2, 3 respectively.

This scheme has CFL coefficient equal to 1 and it is TVD (total variation diminishing).

Fields

  • α¹, α², α³: Stage coefficients (1, 1/4, 2/3)
  • U⁰: Storage for state at beginning of time step
  • Gⁿ: Tendency fields at current stage
  • implicit_solver: Optional implicit solver for diffusion
  • rounding: Round-off treatment of the stage updates, RoundToNearest or StochasticRounding
source
Breeze.TimeSteppers.SSPRungeKutta3 — Method
SSPRungeKutta3(
    grid,
    prognostic_fields;
    dynamics=nothing,
    implicit_solver::TI=nothing,
    cache_advecting_state=false,
    Gⁿ::TG=map(similar, prognostic_fields),
    U⁰::U0=map(similar, prognostic_fields),
    rounding=RoundToNearest()
) where {TI, TG, U0} -> SSPRungeKutta3{<:Any, <:Any, <:Any, Nothing, RoundToNearest}

Construct an SSPRungeKutta3 on grid with prognostic_fields as described by Shu and Osher (1988).

Keyword Arguments

  • implicit_solver: Optional implicit solver for diffusion. Default: nothing
  • Gⁿ: Tendency fields at current stage. Default: similar to prognostic_fields
  • U⁰: Storage for the state at the beginning of the step. Default: similar to prognostic_fields. Accepting it as a keyword lets callers (e.g. the adiabatic-balance twin) alias another stepper's tendency storage instead of allocating fresh fields.
  • rounding: Round-off treatment of the stage updates. Default: RoundToNearest. With StochasticRounding, each stage is evaluated in increment form, $u^{(m)} = u^{(0)} + α \left[ (u^{(m-1)} - u^{(0)}) + Δt \, G \right]$, and the sum is rounded stochastically, so increments below the resolution of $u$ are not lost on average. The vertically-implicit solves and the pressure correction stay round-to-nearest.
using Oceananigans, Breezegrid = RectilinearGrid(Float32; size=(4, 4, 4), extent=(1, 1, 1))model = AtmosphereModel(grid; timestepper_kwargs = (; rounding = StochasticRounding(seed = 42)))model.timestepper.rounding# outputStochasticRounding(seed=42, summation=WidenedSum())

References

Shu, C.-W., & Osher, S. (1988). Efficient implementation of essentially non-oscillatory shock-capturing schemes. Journal of Computational Physics, 77(2), 439-471.

source
Breeze.TimeSteppers.prepare_first_time_step! — Method
prepare_first_time_step!(model, Δt)

Prepare model, at iteration 0, for a first time step of Δt: set clock.last_Δt, reconcile the state and update_state!, which at initialization also computes the initial radiative fluxes. time_step! does this itself at iteration 0 (maybe_prepare_first_time_step!), so eager stepping needs no call.

Under Reactant the iteration is traced, so time_step! cannot tell that it starts the run and skips the preparation. A traced loop of time_step! (a calibration window, say) then calls prepare_first_time_step! before the loop; BreezeReactantExt computes the initial radiative fluxes explicitly there, and refreshes the tendencies with them. Without it the first step would use the diffusivities, tendencies and radiative fluxes the model held before the trace.

using Breezeusing Breeze.TimeSteppers: prepare_first_time_step!grid = RectilinearGrid(size=4, z=(0, 1000), topology=(Flat, Flat, Bounded))model = AtmosphereModel(grid)prepare_first_time_step!(model, 10)model.clock.last_Δt# output10.0
source
Breeze.TimeSteppers.ssp_rk3_substep! — Method
ssp_rk3_substep!(model, Δt, α)

Apply an SSP RK3 substep with coefficient $α$:

\[u^{(m)} = (1 - α) u^{(0)} + α \left[ u^{(m-1)} + Δt \, G \right]\]

where $u^{(0)}$ is stored in the time stepper, $u^{(m-1)}$ is the current field value, and $G$ is the current tendency. The sum is rounded by the time stepper's round-off treatment (see StochasticRounding).

source
Oceananigans.TimeSteppers.maybe_prepare_first_time_step! — Method
maybe_prepare_first_time_step!(
    model::AtmosphereModel{<:CompressibleDynamics, <:Any, Arc, <:AcousticRungeKutta3} where Arc,
    Δt,
    callbacks
)

Seed clock.last_stage_Δt before the first step (or for a clock carrying a non-finite value) with the increment a completed third stage leaves, $(1 - β₂) Δt$ — what adaptive_advection_timestep inverts at stage 1. PerturbationAdvection open boundaries read the same field.

Also seed the substepper's time-averaged transport velocity before the first tendencies are built, then freeze the copy that the first stage's implicit remainder splits.

source

TurbulenceClosures

Breeze.TurbulenceClosures.AbstractMixingLength — Type
abstract type AbstractMixingLength

Supertype of the formulations of the primary mixing length $ℓ$ of TKEBasedTurbulenceClosure. All are built from two lengths: the wall length $ℂˢ z$, $ℂˢ$ times the height above the surface, and the buoyancy penetration depth

\[ℓᵇ = \frac{\sqrt{e}}{N},\]

how far an eddy with kinetic energy $e$ penetrates air of buoyancy frequency $N$ before its kinetic energy is spent against buoyancy — infinite where $N² ≤ 0$. Each formulation carries a wall coefficient $ℂˢ$; the gradient-limited form also carries an independent interior slope $ℂⁱ$. The penetration depth carries no coefficient. The standalone default $ℂˢ = 1.316$ is the reciprocal of Deardorff's coefficient $0.76$ of the stratification length (Deardorff 1980), which the equivalent normalization $ℓ = \min(z, 0.76 \sqrt{e} / N)$ carries on $ℓᵇ$ instead; see absorb_stratification_coefficient. In a neutral surface layer every formulation gives $ℓ = ℂˢ z$ and in uniformly stratified air every formulation gives $ℓ = ℓᵇ$; they differ in what else bounds $ℓ$. The formulations are LocalMinimumMixingLength, IntegralMixingLength and the default GradientLimitedMixingLength.

source
Breeze.TurbulenceClosures.ConstantStabilityFunctions — Type
struct ConstantStabilityFunctions{FT}

Constant stability functions for TKEBasedTurbulenceClosure: the mixing lengths for momentum, tracers and turbulent kinetic energy are constant multiples of the primary length $ℓ$,

\[ℓᵘ = ℂᵘ ℓ, \qquad ℓᶜ = ℂᶜ ℓ, \qquad ℓᵉ = ℂᵉ ℓ,\]

and the dissipation length is $ℓᴰ = ℓ / ℂᴰ$, so that $ε = ℂᴰ e^{3/2} / ℓ$.

The turbulent Prandtl number is $Pr = ℂᵘ / ℂᶜ$ and the TKE Schmidt number $ℂᵘ / ℂᵉ$. In a neutral constant-stress layer, where $ℓ = ℂˢ z$ with $ℂˢ$ the wall coefficient of AbstractMixingLength, production balances dissipation at $e / u_\star² = 1 / \sqrt{ℂᵘ ℂᴰ}$ with a logarithmic wind profile of von Kármán constant $κ = ℂˢ (ℂᵘ³ / ℂᴰ)^{1/4}$; in stratified steady state, where $ℓ = \sqrt{e} / N$, the gradient Richardson number is $Ri^\dagger = ℂᵘ / (ℂᶜ + ℂᴰ)$.

The defaults are the Mellor–Yamada coefficients of Nakanishi and Niino (2009) re-expressed for this normalization of the mixing length ($κ = 0.4$, $e/u_\star² = 4.2$, $Pr = 0.74$, $Ri^\dagger = 0.25$); they are placeholders for calibration. The conversion from the normalization $ℓ = \min(z, Cᴺ \sqrt{e} / N)$ is absorb_stratification_coefficient.

Fields

  • ℂᵘ::Any = 0.149: momentum stability function, $ℓᵘ = ℂᵘ ℓ$

  • ℂᶜ::Any = 0.201: tracer stability function, $ℓᶜ = ℂᶜ ℓ$

  • ℂᵉ::Any = 0.298: turbulent kinetic energy stability function, $ℓᵉ = ℂᵉ ℓ$

  • ℂᴰ::Any = 0.388: dissipation stability function, $ℓᴰ = ℓ / ℂᴰ$

source
Breeze.TurbulenceClosures.DryStaticStability — Type
struct DryStaticStability

The static stability of TKEBasedTurbulenceClosure as the vertical gradient of the buoyancy of the dynamics, $N² = ∂_z b = g ∂_z \ln θᵨ$ with $θᵨ$ the density potential temperature: the stratification a parcel feels when displaced without phase change. Condensate loading is included; the latent heating of a saturated displacement is not. The default is MoistStaticStability, which reduces to this where the air is subsaturated.

source
Breeze.TurbulenceClosures.GradientLimitedMixingLength — Type
struct GradientLimitedMixingLength{FT} <: AbstractMixingLength

A gradient-limited mixing length with independent wall coefficient $ℂˢ$ and interior slope $ℂⁱ$:

\[ℓ(z) = \min\left(ℂˢ z, \min_{z′ > 0} [ℓᵇ(z′) + ℂⁱ |z - z′|]\right).\]

Two sweeps per column compute the stratification envelope; the surface length bounds the result separately. The uncapped envelope is retained for cell-center reconstruction, so changing $ℂⁱ$ does not change the neutral wall length $ℂˢ z$. The domain top is not an obstacle. With equal slopes this recovers the original gradient-limited formulation (Gaspar et al. 1990).

The standalone constructor retains ℂˢ = 1.316 and ℂⁱ = ℂˢ for compatibility: a single positional coefficient or a lone ℂˢ keyword still sets both slopes. TKEBasedTurbulenceClosure supplies the calibrated pair instead.

source
Breeze.TurbulenceClosures.IntegralMixingLength — Type
struct IntegralMixingLength{FT} <: AbstractMixingLength

The mixing length from the parcel displacements of Bougeault and Lacarrère (1989): a parcel released at height $z$ with kinetic energy $e★$ rises until the buoyancy deficit it accumulates has consumed that energy, and likewise sinks,

\[∫_0^{ℓ↑} [b(z) - b(z + s)] \, ds = e★, \qquad ∫_0^{ℓ↓} [b(z - s) - b(z)] \, ds = e★, \qquad ℓ↓ ≤ z,\]

and the mixing length is $ℓ = ℂˢ \min(ℓ↑, ℓ↓)$, the combination of the original paper. The parcel's energy is $e★ = e / (2 ℂˢ²)$ so that the formulation coincides with the others in the two limits every formulation shares: against the ground $ℓ↓ = z$ and $ℓ = ℂˢ z$, and in uniform stratification the deficit is $N² s² / 2$ and $ℓ = ℓᵇ = \sqrt{e} / N$. Unlike GradientLimitedMixingLength it carries the parcel's own energy into the air it penetrates and credits the energy a parcel gains crossing unstable air, so it penetrates inversions and mixes convective layers more. Its cost is a walk per face whose length depends on the state — one to three cells in stratified air, the depth of a mixed layer inside one — so its kernel has data-dependent loop lengths; the top of the domain is not an obstacle. The buoyancy differences along the path are integrated from the stored $N²$.

source
Breeze.TurbulenceClosures.LocalMinimumMixingLength — Type
struct LocalMinimumMixingLength{FT} <: AbstractMixingLength

The mixing length as the smaller of the wall length and the buoyancy penetration depth at the eddy's own level,

\[ℓ = \min(ℂˢ z, \, ℓᵇ),\]

the form of Deardorff (1980) and of Nakanishi and Niino's closure without its turbulent-layer depth scale. It is local: it knows two obstacles, the ground and the stratification at the level itself. In an elevated layer whose static stability is not positive — a saturated cloud layer under MoistStaticStability, a neutral layer — $ℓᵇ$ is infinite and nothing bounds $ℓ$ but the distance to the ground, so $ℓ = ℂˢ z$ reaches kilometers and the diffusivity $ℂᵘ ℓ \sqrt{e}$ jumps by orders of magnitude when such a layer forms, mixes it away within a time step and collapses. GradientLimitedMixingLength, the default, adds the missing bound.

source
Breeze.TurbulenceClosures.RationalStabilityFunction — Method
RationalStabilityFunction(;
    ℂᵘ⁻=1.1960500785675194,
    ℂᵘ⁰=0.15439310625401925,
    ℂᵘ⁺=1.0096744642432665,
    ℂᶜ⁻=2.075340382068647,
    ℂᶜ⁰=0.1929919973602801,
    ℂᶜ⁺=0.2765103939865155,
    ℂᵉ⁻=312.08023980290073,
    ℂᵉ⁰=0.07346835007570773,
    ℂᵉ⁺=16.44560801745103,
    ℂᴰ⁻=2.594967714500517,
    ℂᴰ⁰=0.055354972995243425,
    ℂᴰ⁺=0.05068986128741995,
    Ri⁻=6.562979157594204,
    Ri⁺=15.12797320010583
) -> RationalStabilityFunction{Float64}

Construct rational stability functions for momentum, tracers, TKE, and dissipation: S(Ri) = C⁰ + (C± - C⁰) x / (1 + x), where x = |Ri| / Ri±. Each function has unstable, neutral, and stable endpoints; the four functions share transition scales Ri⁻, Ri⁺. All coefficients must be positive. The functions are continuous, with a kink at neutral. Mixed integer and float arguments are promoted to a single float type.

Defaults are calibrated to the Shen et al. (2022) LES library, as described in the turbulence-closure manual; use TKEBasedTurbulenceClosure() for its paired mixing-length coefficients.

using BreezeRationalStabilityFunction().Ri⁺# output15.12797320010583
source
Breeze.TurbulenceClosures.TKEBasedTurbulenceClosure — Type
struct TKEBasedTurbulenceClosure{TD, ML, SF, SS, FT} <: Oceananigans.TurbulenceClosures.AbstractScalarDiffusivity{TD, Oceananigans.TurbulenceClosures.VerticalFormulation, 2}

A vertical eddy-diffusivity closure carrying one prognostic equation for the subgrid turbulent kinetic energy $e$, in the spirit of CATKE (Wagner et al. 2025):

\[Kᵘ = Sᵘ ℓ \sqrt{e}, \qquad Kᶜ = Sᶜ ℓ \sqrt{e}, \qquad Kᵉ = Sᵉ ℓ \sqrt{e}, \qquad ε = Sᴰ e^{3/2} / ℓ,\]

\[∂_t (ρ e) + ∇ ⋅ (ρ 𝐮 e) = ∂_z (ρ Kᵉ ∂_z e) + ρ (P + B - ε), \qquad P = Kᵘ S², \qquad B = -Kᶜ N²,\]

where $Kᵘ$, $Kᶜ$ and $Kᵉ$ are the eddy diffusivities of momentum, scalars and turbulent kinetic energy, $S²$ the squared vertical shear, $N²$ the squared buoyancy frequency, $ℓ$ the primary mixing length (AbstractMixingLength: GradientLimitedMixingLength by default, LocalMinimumMixingLength or IntegralMixingLength), and $Sᵘ, Sᶜ, Sᵉ, Sᴰ$ stability functions (ConstantStabilityFunctions or RationalStabilityFunction). $N²$ is diagnosed once per time-step stage at the cell interfaces by the static_stability component (MoistStaticStability by default, or DryStaticStability) and stored with the closure fields. The prognostic TKE density is the tracer ρe, which the closure adds to the model; it is advected and vertically diffused like every other scalar, and the closure applies the local production, buoyancy flux and dissipation.

The square root of $e$ is floored at minimum_tke wherever it enters a diffusivity or a length scale, and negative $e$ — which advection can produce — is damped on negative_tke_damping_time_scale rather than clipped. The three maximum_* diffusivities clip the diffusivities, Inf by default. The Richardson number of RationalStabilityFunction is $Ri = N² / (S² + S²ᵐⁱⁿ)$, with $S²ᵐⁱⁿ$ the minimum_shear_squared, so that it is finite and continuous where the shear vanishes.

source
Breeze.TurbulenceClosures.TKEBasedTurbulenceClosure — Method
TKEBasedTurbulenceClosure(
    time_discretization::TD=VerticallyImplicitTimeDiscretization(),
    FT=Oceananigans.defaults.FloatType;
    mixing_length=GradientLimitedMixingLength(ℂˢ = 0.7877315198717979, ℂⁱ = 1.777871783491512),
    stability_functions=RationalStabilityFunction(),
    static_stability=MoistStaticStability(),
    maximum_viscosity=Inf,
    maximum_tracer_diffusivity=Inf,
    maximum_tke_diffusivity=Inf,
    minimum_tke=1.0e-6,
    minimum_shear_squared=1.0e-10,
    negative_tke_damping_time_scale=1minute
) where TD -> TKEBasedTurbulenceClosure{<:Any, ML, <:Any, MoistStaticStability} where ML<:GradientLimitedMixingLength

Construct a TKEBasedTurbulenceClosure with the given time discretization (default VerticallyImplicitTimeDiscretization()), float type, mixing length, stability functions, static stability and numerical parameters. The defaults are calibrated to the Shen et al. (2022) LES library: rational stability functions, wall coefficient 0.7877315198717979 and interior slope 1.777871783491512.

minimum_shear_squared (default 1e-10 s⁻²) is the floor $S²ᵐⁱⁿ > 0$ added to the squared shear in the Richardson number of RationalStabilityFunction, $Ri = N² / (S² + S²ᵐⁱⁿ)$. It makes the stability functions continuous where the shear vanishes, as in uniform or absent wind, where $N² / S²$ would jump between the stable and unstable limits with the sign of a rounding-level $N²$. There the stability functions pass from neutral to their limits over $|N²| ∼ Ri^± S²ᵐⁱⁿ$; where $S² ≫ S²ᵐⁱⁿ$ they are unchanged to relative order $S²ᵐⁱⁿ / S²$. It does not enter ConstantStabilityFunctions.

using BreezeTKEBasedTurbulenceClosure().minimum_shear_squared# output1.0e-10
source

Utils

Breeze.Utils — Module

Small, scheme-independent helpers shared across Breeze: property sums, guarded arithmetic, the Chebyshev–Gauss quadrature used to tabulate size-distribution integrals, and the @adapt_architecture macro that generates architecture-transfer methods for container structs.

source
Breeze.Utils.chebyshev_gauss_nodes_weights — Method
chebyshev_gauss_nodes_weights(
    FT::DataType,
    n::Int64
) -> Tuple{Vector, Vector}

Compute Chebyshev–Gauss quadrature nodes and weights for n points.

Returns (nodes, weights) for approximating

\[∫_{-1}^{1} f(x) dx ≈ ∑ᵢ wᵢ f(xᵢ)\]

The nodes cluster near the boundaries, which helps capture rapidly-varying contributions of size-distribution integrands.

using Breeze.Utils: chebyshev_gauss_nodes_weightsnodes, weights = chebyshev_gauss_nodes_weights(Float64, 4)round(sum(weights), digits=4)# output2.0523
source
Breeze.Utils.safe_divide — Method
safe_divide(a, b, default)

Return a / b, or default where b is exactly zero. Branch-free, so it is safe inside GPU kernels.

using Breeze.Utils: safe_dividesafe_divide(1.0, 0.0, -1.0)# output-1.0
source
Breeze.Utils.sum_properties — Method
sum_properties(object, names::Tuple{Symbol})

Return the sum of the properties of object selected by the nonempty tuple names. Properties may be scalars, fields, or other values supporting +.

A single selected property is returned unchanged. No scalar zero is added, so the sum also supports lazy field expressions. Callers handle empty selections.

using Breeze.Utils: sum_propertiessum_properties((a=1, b=2, c=4), (:a, :c))# output5
source
Breeze.Utils.transform_to_diameter — Method
transform_to_diameter(x, λ; scale=10)

Map a Chebyshev–Gauss node x ∈ [-1, 1] to a particle diameter D ∈ [0, ∞) using D = (scale/λ) (1+x)/(1-x+ε). The default scale = 10 covers more than 99.99% of an exponential tail with decay length 1/λ.

source
Breeze.Utils.@adapt_architecture — Macro
@adapt_architecture T

Generate Adapt.adapt_structure and Oceananigans.Architectures.on_architecture methods for T that walk every field of T and reconstruct via the positional constructor. T must already be defined when the macro is expanded.

A field-by-field walk leaves scalars untouched, because both Adapt.adapt and on_architecture fall back to the identity for types without specific methods (adapt_storage(to, x) = x, on_architecture(arch, a) = a), so only the array fields are actually transferred.

The invoking module must have Adapt and Oceananigans in scope.

source

VerticalGrids

Breeze.VerticalGrids.PiecewiseStretchedDiscretization — Type
PiecewiseStretchedDiscretization(; z, Δz)

Construct a stretched vertical grid where the spacing varies piecewise-linearly between breakpoints. The grid spacing is specified at breakpoint heights z, and linearly interpolated between them.

Between breakpoints where Δz values are equal, the grid is uniform. Where they differ, the spacing transitions linearly.

The result behaves as a vector of face positions and can be passed directly to RectilinearGrid as a coordinate argument.

Keyword Arguments

  • z: sorted vector of breakpoint heights (length ≥ 2)
  • Δz: vector of grid spacings at each breakpoint (same length as z, all positive)

Examples

A three-region grid with uniform fine spacing, a linear transition, and uniform coarse spacing (as used for tropical cyclone simulations):

z = PiecewiseStretchedDiscretization(    z  = [0, 1000, 3500, 28000],    Δz = [62.5, 62.5, 2000, 2000])Nz = length(z) - 1grid = RectilinearGrid(arch; size=(Nx, Ny, Nz), x=(0, Lx), y=(0, Ly), z)

A four-region grid for deep convection (fine near surface, transition to moderate, uniform through the troposphere, then stretched to the model top):

z = PiecewiseStretchedDiscretization(    z  = [0, 1275, 5100, 18000, 27000],    Δz = [50, 50, 100, 100, 300])
source

BreezeRRTMGPExt

BreezeCloudMicrophysicsExt

BreezeNumericalRadiationExt

Private API

Advection

AnelasticEquations

Breeze.AtmosphereModels.buoyancy_forceᶜᶜᶜ — Method
buoyancy_forceᶜᶜᶜ(
    i,
    j,
    k,
    grid,
    dynamics::AnelasticDynamics,
    temperature,
    specific_prognostic_moisture,
    microphysics,
    microphysical_fields,
    constants
)

Compute the buoyancy force density for anelastic dynamics at cell center (i, j, k).

The anelastic buoyancy force is the gravitational force on the density anomaly:

\[-g ρ' = -g (ρ - ρ_r)\]

where $ρ = p_r / (R^m T)$ is the in-situ density from the ideal gas law, and $ρ_r = p_r / (R^m_r T_r)$ is the reference density. Substituting:

\[\rho' = \frac{p_r}{R^m T} - \frac{p_r}{R^m_r T_r} = \frac{p_r}{R^m_r T_r} \left( \frac{R^m_r T_r}{R^m T} - 1 \right) = \rho_r \left( \frac{R^m_r T_r}{R^m T} - 1 \right)\]

This "perturbation form" avoids subtracting two large, nearly-equal numbers ($p_r / (R^m T) - ρ_r$), which causes catastrophic cancellation when $T ≈ T_r$. Instead, the ratio $R^m_r T_r / (R^m T)$ is close to 1, and the subtraction of 1 preserves relative precision.

Here, $R^m = q^d R^d + q^v R^v$ is the mixture gas constant for the current moisture state and $R^m_r$ is the mixture gas constant for the reference moisture state.

source
Breeze.AtmosphereModels.default_drag_surface_temperature — Method
default_drag_surface_temperature(
    dynamics::AnelasticDynamics,
    grid,
    constants
)

Default surface temperature for BulkDrag under AnelasticDynamics: the reference-state temperature at the bottom face of the domain.

Used only when the user constructs BulkDrag without an explicit surface_temperature. The result is a horizontally uniform scalar.

source
Breeze.AtmosphereModels.default_dynamics — Method
default_dynamics(grid, constants)

Construct a "stub" AnelasticDynamics with just the reference_state. The pressure anomaly field is materialized later in the model constructor.

source
Breeze.AtmosphereModels.pressure_anomaly — Method
pressure_anomaly(dynamics::AnelasticDynamics)

Return the non-hydrostatic pressure anomaly for AnelasticDynamics, in Pa.

Kinematic pressure versus pressure

The internal field stores the kinematic pressure anomaly, i.e., $p' / ρᵣ$ (in m²/s²); this function returns $p'$ in Pa.

source

AtmosphereModels

Breeze.AtmosphereModels.DefaultTimeStepping — Type
struct DefaultTimeStepping

Sentinel for AdiabaticBalancer's default time_stepping: the fully-explicit twin for CompressibleDynamics, and the native scheme for solvers without a separable time discretization (e.g. AnelasticDynamics). It lets the default avoid naming a concrete time discretization, whose type lives in a submodule loaded after AtmosphereModels.

source
Breeze.AtmosphereModels.OutflowEnabledVelocity — Type
struct OutflowEnabledVelocity{W}

Wrap a sedimenting tracer's total vertical velocity so the adaptive implicit solve includes both transport and sedimentation, including outflow through the bottom boundary (see density_weighted_advection_diagonal).

  • velocity::Any
source
Breeze.AtmosphereModels.SedimentingCondensate — Type
struct SedimentingCondensate{W, Q, D, P, A}
  • velocity::Any: Signed vertical sedimentation velocity field [m s⁻¹], negative for downward motion

  • specific_humidity::Any: Specific humidity field of the condensate [kg kg⁻¹]

  • density::Any: Prognostic partial density field the specific humidity is diagnosed from [kg m⁻³]

  • liquid_fraction::Any: Liquid fraction of the mass: 1 liquid, 0 ice (see condensate_liquid_fraction)

  • advection::Any: Advection scheme that transports the condensate mass

A condensate mass that sediments, as model.sedimentation holds it: one for every name in condensate_field_names with a sedimentation_velocity, keyed by that name.

source
Breeze.AtmosphereModels.add_sedimentation_tendency! — Method
add_sedimentation_tendency!(
    G,
    model,
    tracer_transport_velocity
)

Add the explicit condensate sedimentation_tendency of the thermodynamic variable to its tendency G, with tracer_transport_velocity the vertical velocity the moisture and tracer tendencies advect with. The term runs in a kernel of its own rather than inside the thermodynamic tendency kernel: fused, its per-constituent flux reconstructions and condensate contents raise that kernel's register use and cut its occupancy for every cell, whether or not anything sediments there. A no-op when no condensate sediments.

source
Breeze.AtmosphereModels.adiabatic_balance_twin — Function
adiabatic_balance_twin(
    model::AtmosphereModel,
    balancer::AdiabaticBalancer=AdiabaticBalancer()
)

Build a stripped adiabatic twin of model that SHARES all field memory (momentum, velocities, densities, ρθ/ρs, moisture, aerosol number, tracers, temperature, pressure solver, dynamics fields) and steps it in place. Every retained prognostic scalar is rewrapped with its surface fluxes stripped to no-flux (see adiabatic_scalar_bcs), sharing the production data so no memory is reallocated. Prognostic aerosol number is carried as a passive tracer: activation and sedimentation are removed, while reversible transport preserves nᵃ = ρnᵃ / ρ as the balance adjusts density. The twin's dynamics comes from adiabatic_twin_dynamics (per balancer.time_stepping); microphysics, closure, the implicit diffusion solver, the sponge, and forcing are removed; the time stepper's Gⁿ/U⁰ tendency storage aliases the production stepper's same-named arrays (moisture key re-mapped from the microphysics name, e.g. :ρqᵉ, to the moistureless :ρqᵛ); and a fresh Clock is used so the balance's clock reset does not touch the production clock.

source
Breeze.AtmosphereModels.adiabatic_scalar_bcs — Function
adiabatic_scalar_bcs(bcs)

Return a copy of the prognostic-scalar FieldBoundaryConditions bcs with every surface flux replaced by a no-flux condition, leaving all other (dynamical) boundary conditions untouched. Applied to both the thermodynamic density (bulk sensible-heat / energy / θ flux) and the moisture density (vapor flux) to strip surface sources from the adiabatic initialization twin, so its symmetric forward/backward excursion stays pure, reversible dynamics (see balance_adiabatically!). Extended by the BoundaryConditions module, which owns the flux BC types.

source
Breeze.AtmosphereModels.adiabatic_twin_dynamics — Method
adiabatic_twin_dynamics(dynamics, time_stepping)

Return the dynamics for the adiabatic-balance twin, given the production dynamics and the requested time_stepping. The generic fallback reuses dynamics unchanged — correct for solvers without a separable time discretization (e.g. AnelasticDynamics) and for any future solver, keeping the balance solver-agnostic. CompressibleDynamics extends this to swap the time discretization (sponge always stripped, as it is irreversible).

source
Breeze.AtmosphereModels.adjust_thermodynamic_state — Method
adjust_thermodynamic_state(state, scheme::Nothing, thermo)

Adjust the thermodynamic state according to the scheme. For example, if scheme isa SaturationAdjustment, then this function will adjust and return a new thermodynamic state given the specifications of the saturation adjustment scheme.

If a scheme is non-adjusting, we just return state.

source
Breeze.AtmosphereModels.advecting_vertical_velocity — Method
advecting_vertical_velocity(dynamics, velocities)

Return the vertical velocity that advects momentum through the grid's coordinate surfaces: the Cartesian velocities.w on height-coordinate grids, and the contravariant vertical velocity w̃ on terrain-following grids (mirroring advecting_momentum, whose vertical component is the contravariant momentum). The adaptive-implicit vertical-advection split must partition this velocity on both the explicit (flux-scaling) and implicit (tridiagonal) sides, so it stays consistent with the momentum flux divergence.

source
Breeze.AtmosphereModels.auxiliary_model_fields — Method
auxiliary_model_fields(
    temperature
) -> NamedTuple{(:T,), <:Tuple{Any}}

The non-prognostic fields exposed alongside the prognostic ones by Oceananigans.fields(model), which is the temperature and nothing else. Forcings and boundary functions resolve their field_dependencies to positional indices into this tuple and index it with those at runtime, so every site that assembles the model's field tuple must obtain the auxiliaries here rather than rebuild the tuple, and every entry must adapt to the same device-side type.

That second requirement is what keeps the thermodynamic pressure and density out: Adapt.adapt_structure unwraps a three-dimensional Field to its OffsetArray but preserves the Field around a dimension-reduced one, such as an anelastic reference profile, so admitting them would make the positional lookup a non-concrete Union and the GPU compiler would then reject every kernel that performs one. Boundary conditions receive them as a second tuple instead, from dynamics_thermodynamic_fields, and read them by name.

source
Breeze.AtmosphereModels.base_pressure — Function
base_pressure(dynamics)

Return the pressure of the reference atmosphere at $z = 0$: the datum its hydrostatic profiles are anchored to, and a property of that atmosphere rather than of the grid. Always a scalar.

This is not the pressure at the ground. On a domain whose bottom does not sit at $z = 0$ — a raised height-coordinate domain, or any terrain-following grid — the two differ by $O(ρgh)$. For the pressure at the ground, which is what a column integration is anchored at, use surface_pressure.

source
Breeze.AtmosphereModels.closure_scalar_index — Method
closure_scalar_index(
    model::AtmosphereModel,
    name::Symbol
) -> Union{Nothing, Val}

The index under which the prognostic field name enters the vertically-implicit solve: nothing for momentum, which is diffused with the closure's viscosity, and Val(i) for the ith closure scalar, which is diffused with diffusivity(closure, closure_fields, Val(i)).

source
Breeze.AtmosphereModels.cloud_liquid_effective_radius — Method
cloud_liquid_effective_radius(
    i,
    j,
    k,
    grid,
    effective_radius_model::ConstantRadiusParticles,
    args...
)

Return the effective radius of cloud liquid droplets in meters.

This function dispatches on the effective_radius_model argument. The default implementation for ConstantRadiusParticles returns a constant value.

Microphysics schemes can extend this function to provide diagnosed effective radii based on cloud properties.

source
Breeze.AtmosphereModels.column_index — Method
column_index(i, j, Nx)

The column index c = i + (j - 1) Nx of horizontal cell (i, j): every column-based radiation backend stores its per-column arrays in this order.

source
Breeze.AtmosphereModels.compute_auxiliary_dynamics_variables! — Method
compute_auxiliary_dynamics_variables!(model)

Compute auxiliary (diagnostic) variables specific to the dynamics formulation.

For anelastic dynamics, this is a no-op (pressure is computed during time-stepping via the pressure Poisson equation).

For compressible dynamics, this computes the pressure field from the equation of state:

\[p = ρ R^m T\]

where $R^m$ is the mixture gas constant.

source
Breeze.AtmosphereModels.compute_auxiliary_variables! — Method
compute_auxiliary_variables!(model)

Compute auxiliary model variables:

  • velocities from momentum and density (eg $u = ρu / ρ$)

  • thermodynamic variables from the prognostic thermodynamic state,

    • temperature $T$, possibly involving saturation adjustment
    • specific thermodynamic variable ($s = ρs / ρ$ or $θ = ρθ / ρ$)
    • moisture mass fraction $qᵗ = ρqᵗ / ρ$
source
Breeze.AtmosphereModels.compute_closure_tendencies! — Method
compute_closure_tendencies!(model)

Add a turbulence closure's own tendencies — the local sources of a prognostic the closure carries, such as the shear and buoyancy production of turbulent kinetic energy — to the model's tendencies Gⁿ. The time steppers call this at the start of every stage, after compute_flux_bc_tendencies!. A no-op for closures that carry no prognostic.

source
Breeze.AtmosphereModels.compute_dynamics_tendency! — Method
compute_dynamics_tendency!(model)

Compute tendencies for dynamics-specific prognostic fields.

For anelastic dynamics, this is a no-op (no prognostic density). For compressible dynamics, this computes the density tendency from the continuity equation:

\[\partial_t \rho = -\boldsymbol{\nabla \cdot \,} (\rho \boldsymbol{u})\]

source
Breeze.AtmosphereModels.compute_radiation_flux_divergence! — Method
compute_radiation_flux_divergence!(rtm, grid)

Compute rtm.flux_divergence = -∂F_net/∂z (W m⁻³) from the four ZFaceField fluxes of rtm, with F_net the sum of the up- and downwelling longwave and shortwave fluxes, all signed positive upward (downwelling fluxes are stored negative).

source
Breeze.AtmosphereModels.compute_thermodynamic_tendency! — Function
compute_thermodynamic_tendency!(model, common_args, tracer_transport_velocity)

Compute the thermodynamic tendency. Dispatches on the thermodynamic formulation type. common_args are the arguments the scalar tendencies share, and tracer_transport_velocity the vertical velocity the moisture and tracer tendencies were built with, which the condensate sedimentation term pairs its content fluxes with (see sedimentation_tendency). The two need not agree: a time stepper may advect the thermodynamic variable with a velocity its tracers do not share.

source
Breeze.AtmosphereModels.condensate_content — Function

Return the condensate content of the thermodynamic variable of formulation at cell (i, j, k), as (; χ = (χˡ, χⁱ), h = (hˡ, hⁱ), ∂φ∂h): per phase the content χˣ = ∂φ/∂qˣ of the specific variable φ at fixed temperature along the dynamics' composition increment (sedimentation_composition_increment); per phase the enthalpy the falling mass carries (phase enthalpy hˣ on the compressible core, hˣ − hᵈ under the fixed-density convention); and ∂φ/∂h, the local response of φ to heating: one for s, and for θˡⁱ 1 / (ĉᵖ Π) at prescribed pressure (the anelastic core) or the fixed-gas-density response β_cv on the compressible core (see sedimentation_thermal_response). Each thermodynamic formulation extends this function for its formulation type. The remaining arguments are the model's dynamics, thermodynamic constants, microphysics and microphysical_fields, prognostic specific_prognostic_moisture, and temperature field. sedimentation_tendency consumes the content.

source
Breeze.AtmosphereModels.condensate_field_names — Method
condensate_field_names(microphysics)

Return the names of the prognostic microphysical fields that carry condensate mass (condensate and precipitation densities), excluding number-concentration fields.

This is the subset of prognostic_field_names that, together with the moisture density, is summed by total_condensate_density to form the total condensate mass per unit volume. It defaults to all prognostic fields; schemes with prognostic number concentrations (e.g. two-moment) override it to drop the ρnˣ fields.

source
Breeze.AtmosphereModels.constant_field_property — Method
constant_field_property(
    x::Number,
    FT
) -> Oceananigans.Fields.ConstantField{<:Any, 3}

Wrap a scalar surface property in a ConstantField of the working precision, passing anything already field-valued through unchanged, so that emissivity and both albedos are uniformly field-valued whether the user supplied a number, a field, or a dataset.

source
Breeze.AtmosphereModels.content_temperature — Method
content_temperature(formulation, temperature_field)

Return the temperature argument implicit_sedimentation_step! passes to condensate_content for formulation: the model's temperature_field by default, or nothing for a formulation whose content rediagnoses the temperature from the post-solve state, which the tracers' solves have moved away from the one the temperature field was diagnosed from.

source
Breeze.AtmosphereModels.convert_total_moisture! — Method
convert_total_moisture!(model)

Convert the total-water density staged by set! in model.moisture_density into the scheme's prognostic moisture density by subtracting the independent condensate densities, $ρqᵛᵉ = ρqᵗ - Σ ρqᶜ$, then diagnose the specific prognostic moisture $qᵛᵉ = ρqᵛᵉ / ρ$ from the established total air density. The subtraction involves no density, so the supplied water budget is preserved exactly.

Reject condensate exceeding total water beyond local round-off tolerance. Retain round-off-sized residuals so the conversion preserves the supplied water budget. Inside a compiled program, where the rejection cannot raise, an invalid state's moisture is NaN instead.

source
Breeze.AtmosphereModels.correction_moisture_fields — Method
correction_moisture_fields(
    microphysics,
    microphysical_fields
) -> Tuple{}

Return a tuple of Field objects for density-weighted prognostic moisture mass fields that participate in the negative-moisture correction, ordered from heaviest hydrometeor to lightest.

Each field borrows from the next in the chain. The lightest field borrows from the moisture prognostic (vapor or equilibrium moisture, stored in model.moisture_density). Remaining vapor deficits are fixed by vertical borrowing when enabled.

Default: empty tuple (no correction).

source
Breeze.AtmosphereModels.correction_number_fields — Method
correction_number_fields(
    microphysics,
    microphysical_fields
) -> Tuple{}

Return a tuple of Field objects for density-weighted number concentration fields that should be clamped to non-negative after advection.

Number concentrations can become negative because the advection scheme might not be positive-definite. Unlike mass fields (which use borrowing to preserve conservation), number concentrations are simply zeroed since there is no meaningful conservation constraint for droplet number.

Only called for microphysics whose categories subtype AbstractNumberConcentrationCategories.

Default: empty tuple (no number fields to clamp).

source
Breeze.AtmosphereModels.correction_number_mass_pairs — Method
correction_number_mass_pairs(
    microphysics,
    microphysical_fields
) -> Tuple{}

Return a tuple of (number_field, mass_field) pairs for number concentration consistency. After species borrowing, any number field whose corresponding mass field is non-positive is zeroed to avoid unphysical states (e.g., finite droplet number with zero mass).

Only called for microphysics whose categories subtype AbstractNumberConcentrationCategories.

Default: empty tuple (no number fields to correct).

source
Breeze.AtmosphereModels.default_drag_surface_temperature — Method
default_drag_surface_temperature(
    dynamics,
    grid,
    thermodynamic_constants
)

Return a default surface temperature for BulkDrag when the user has not supplied one. Dispatched on the dynamics type because the notion of a "default" surface temperature depends on what reference structure the dynamics carries: anelastic has a full reference profile whose surface value is well-defined; compressible has no equivalent up-front surface temperature and therefore requires the user to provide one explicitly.

The default (no method) throws an informative error. Each dynamics type extends this hook.

source
Breeze.AtmosphereModels.default_timestepper — Method
default_timestepper(dynamics) -> Symbol

Return the default timestepper symbol for the given dynamics.

For anelastic dynamics or compressible dynamics with explicit timestepping, returns :SSPRungeKutta3. For compressible dynamics with acoustic substepping, returns :AcousticRungeKutta3.

source
Breeze.AtmosphereModels.density_potential_temperature — Method
density_potential_temperature(
    i,
    j,
    k,
    grid,
    b::Breeze.AtmosphereModels.AtmosphereModelBuoyancy,
    T,
    qᵛᵉ
)

The density potential temperature at cell (i, j, k),

\[θᵨ = \frac{Rᵐ}{Rᵈ} \, T \left( \frac{pˢᵗ}{p} \right)^{Rᵈ / cᵖᵈ}, \qquad Rᵐ = qᵈ Rᵈ + qᵛ Rᵛ, \qquad qᵈ = 1 - qᵛ - qˡ - qⁱ,\]

the potential temperature of the dry air that has the density of the moist, condensate-laden air at the same pressure. Since $ρ = p / (Rᵐ T)$, at fixed pressure $θᵨ ∝ 1 / ρ$ and the buoyancy of the dynamics is $b = -g ρ′ / ρᵣ ≈ g \, θᵨ′ / θᵨ$; condensate enters through the dry-air mass fraction $qᵈ$, so that liquid and ice water load the air by their mass. The moisture mass fractions come from the microphysics through grid_moisture_fractions, supplied with the prognostic specific moisture qᵛᵉ (vapor or equilibrium moisture, depending on the scheme), and the pressure is the dynamics pressure.

source
Breeze.AtmosphereModels.diagnose_thermodynamic_state — Function
diagnose_thermodynamic_state(i, j, k, grid, formulation, dynamics, q)

Diagnose the thermodynamic state at grid point (i, j, k) from the given formulation, dynamics, and pre-computed moisture mass fractions q.

Moisture mass fractions computation

This function does not compute moisture fractions internally to avoid circular dependencies. The caller is responsible for computing q = grid_moisture_fractions(...) before passing q to this function.

source
Breeze.AtmosphereModels.dynamics_prognostic_fields — Method
dynamics_prognostic_fields(dynamics) -> @NamedTuple{}

Return a NamedTuple of prognostic fields specific to the dynamics formulation.

For anelastic dynamics, returns an empty NamedTuple. For compressible dynamics, returns (ρ=density_field,).

source
Breeze.AtmosphereModels.dynamics_reference_state — Method
dynamics_reference_state(dynamics)

Return the dynamics' reference state (an anelastic ReferenceState or a split-explicit ExnerReferenceState), or nothing if the dynamics carries none. Dispatched so that reset_reference_state! needn't reach into fields by name.

source
Breeze.AtmosphereModels.dynamics_thermodynamic_fields — Method
dynamics_thermodynamic_fields(
    dynamics
) -> NamedTuple{(:p, :ρ), <:Tuple{Any, Any}}

The pressure and density the model's own thermodynamics is evaluated with, which surface-flux boundary conditions read to diagnose the surface state below (i, j). boundary_condition_args passes this tuple after the model field tuple, and Breeze's own boundary conditions merge the two; see auxiliary_model_fields for why it has to arrive separately.

These are dynamics_pressure and total_density, both of which are always actual Fields: prognostic under CompressibleDynamics, the hydrostatic reference profile under AnelasticDynamics. Deliberately not total_pressure, which for anelastic dynamics is a lazy sum that would rebuild an AbstractOperation on every halo fill, and whose nonhydrostatic anomaly is a Lagrange multiplier defined only up to a constant, so no surface diagnostic should depend on it.

source
Breeze.AtmosphereModels.establish_densities! — Function
establish_densities!(
    model,
    total_density_given,
    dry_density_given,
    moisture_given=false,
    specific_moisture_given=false,
    total_moisture_given=false,
    specific_microphysical_names=()
)

Mid-set! hook (run after density + moisture are set, before the thermodynamic variable and velocities) that makes the dry density ρᵈ and the diagnosed total density ρ mutually consistent and available to the phase-2 kernels. The two density-input modes need different computations:

  • total_density_given (:ρ): the field holds the total ρ (placeholder); split it into the total-density field and back out ρᵈ = ρ − Σρqˣ (the moisture partial densities were already weighted by the total).
  • dry_density_given (:ρᵈ): the field holds ρᵈ; recover the total ρ = ρᵈ/qᵈ (with qᵈ = 1 − qᵗ, taking the moisture into account) and (re)weight the moisture partial densities ρqˣ = ρ·qˣ.
  • neither: diagnose ρ = ρᵈ + Σρqˣ from the existing fields.

No-op by default (single-density formulations like anelastic, where total_density === continuity_density); CompressibleModel overrides it.

source
Breeze.AtmosphereModels.establish_relative_humidity_densities! — Function
establish_relative_humidity_densities!(
    model,
    total_density_given,
    specific_microphysical_names=()
)

Reconcile dry and total density after relative humidity has diagnosed specific vapor.

Relative humidity is evaluated only after the thermodynamic state is available, later than the usual establish_densities! pass. Compressible dynamics overrides this hook to preserve a supplied total density, or otherwise preserve dry density, while converting the diagnosed vapor and any specifically supplied microphysical moments to total-density-weighted prognostics.

source
Breeze.AtmosphereModels.extract_microphysical_prognostics — Method
extract_microphysical_prognostics(
    i,
    j,
    k,
    microphysics,
    μ_fields
) -> NamedTuple

Extract prognostic microphysical variables at grid point (i, j, k) into a NamedTuple of scalar values.

Uses prognostic_field_names to determine which fields to extract. The result is a NamedTuple with density-weighted values (e.g., (ρqᶜˡ=..., ρqʳ=...)).

This function enables a generic grid-indexed microphysical_state that extracts prognostics and delegates to the gridless version.

source
Breeze.AtmosphereModels.fix_negative_moisture! — Method
fix_negative_moisture!(model)

Fix negative moisture mixing ratios produced by the advection operator.

Operates in one or two phases depending on the correction scheme:

  1. Species borrowing (SpeciesBorrowing, optional): at each grid cell, negative hydrometeors borrow from lighter species (rain <- cloud <- vapor).
  2. Vertical borrowing (VerticalBorrowing, optional): negative vapor is redistributed vertically within each column (top->bottom sweep, then one bottom->top step).

For microphysics with number concentrations (categories subtying AbstractNumberConcentrationCategories), orphaned number concentrations are zeroed and negatives are clamped after mass borrowing.

The correction is mass-conserving at each level for species borrowing and column-integrated for vertical borrowing. No energy adjustment is needed because Breeze's thermodynamic prognostics are moist-conserved variables.

The borrowing chain is defined by correction_moisture_fields, which microphysics schemes extend to specify their prognostic mass fields.

source
Breeze.AtmosphereModels.geometric_stretching_ratio — Method
geometric_stretching_ratio(Δz₁, depth, N)

The ratio r between successive layers of a geometric stretching of N layers whose first layer is Δz₁ thick and which together span depth, i.e. the root of

\[Δz₁ (1 + r + ⋯ + rᴺ⁻¹) = depth ,\]

found by bisection. The left-hand side increases monotonically with r from Δz₁ (as r → 0), so the root exists and is unique for any depth > Δz₁; it is greater than one when depth > N Δz₁ (layers grow with height) and less than one otherwise. For N = 1 the ratio is immaterial and 1 is returned.

source
Breeze.AtmosphereModels.grid_microphysical_state — Method
grid_microphysical_state(
    i,
    j,
    k,
    grid,
    microphysics,
    μ_fields,
    ρ,
    𝒰,
    velocities
)

Build an AbstractMicrophysicalState (ℳ) at grid point (i, j, k).

This is the grid-indexed wrapper that:

  1. Extracts prognostic values from μ_fields via extract_microphysical_prognostics
  2. Calls the gridless microphysical_state(microphysics, ρ, μ, 𝒰, velocities)

Microphysics schemes should implement the gridless version, not this one.

Arguments

  • i, j, k: Grid indices
  • grid: The computational grid
  • microphysics: The microphysics scheme
  • μ_fields: NamedTuple of microphysical fields
  • ρ: Local density (scalar)
  • 𝒰: Thermodynamic state
  • velocities: Velocity fields $(u, v, w)$. Velocities are interpolated to cell centers for use by microphysics schemes (e.g., aerosol activation uses vertical velocity).

Returns

An AbstractMicrophysicalState subtype containing the local microphysical variables.

See also microphysical_tendency, AbstractMicrophysicalState.

source
Breeze.AtmosphereModels.implicit_sedimentation_mass_fluxes — Method
implicit_sedimentation_mass_fluxes(
    i,
    j,
    k,
    grid,
    advection,
    wᵗ,
    wˢ,
    ρq,
    ρ
) -> Tuple{Tuple{Any, Any}, Tuple{Any, Any}}

Like sedimentation_mass_fluxes, but the first-order upwind remainder that the adaptive implicit vertical solve applies to the tracer, evaluated at the solved state ρq / ρ with the prognostic density ρq and the density ρ the solve reconstructs the humidity from. Zero for a scheme without an adaptive-implicit vertical discretization; the adaptive-implicit method mirrors the solve's coefficients (see density_weighted_implicit_diffusion.jl).

source
Breeze.AtmosphereModels.implicit_sedimentation_step! — Function
implicit_sedimentation_step!(
    model,
    Δt,
    velocities,
    formulation=model.formulation
)

Move the condensate content of the thermodynamic variable with the sedimentation mass that the adaptive implicit vertical solve has just applied to the tracers: add Δt times the sedimentation tendency of the first-order remainder the solves applied, at the solved state, to the thermodynamic_density (the tendency of sedimentation_tendency formed from implicit_sedimentation_mass_fluxes). velocities are the transport velocities whose vertical component the tracers' solves split, Δt the interval they solved over, and formulation selects the condensate_content methods, defaulting to the model's. The time steppers call this between the tracers' solves of a stage and the thermodynamic variable's post-loop solve, so the moved content takes the same implicit diffusion as the rest of the field, and on the SSP path its implicit vertical transport too; the acoustic stepper applies that transport inside its substep loop, before this step (see the note above). A no-op when no condensate is advected adaptively implicitly.

For potential temperature this is a derivative-times-increment update, not an exact finite thermal-energy reconstruction. Matching the implicit mass flux alone does not remove that finite-step error.

source
Breeze.AtmosphereModels.initialize_cos_zenith! — Method
initialize_cos_zenith!(cos_zenith, ::ApparentSolarPosition)

Fill cos_zenith once at construction from the solar-position specification.

ApparentSolarPosition and DiurnalSolarPosition need no pre-fill: update_cos_zenith! populates the array on the first radiation update (iteration 0 always triggers one). FixedCosineZenith writes the user-supplied value here; after this the array is never touched, since update_cos_zenith! is a no-op for that case.

source
Breeze.AtmosphereModels.initialize_model_thermodynamics! — Method
initialize_model_thermodynamics!(model)

Initialize the thermodynamic state for a newly constructed model. For anelastic dynamics, sets initial θ to the reference potential temperature. For compressible dynamics, no default initialization is performed.

source
Breeze.AtmosphereModels.liquid_ice_exner_exponent — Method
liquid_ice_exner_exponent(
    formulation
) -> VaporEquivalentExponent

Return the Exner exponent (VaporEquivalentExponent or DryExponent) that defines the liquid-ice potential temperature $θˡⁱ$ of formulation. A formulation that does not evolve $θˡⁱ$, and the symbol :LiquidIcePotentialTemperature, return the default VaporEquivalentExponent(), so diagnostics and boundary-flux conversions of $θˡⁱ$ agree with the definition the formulation evolves.

source
Breeze.AtmosphereModels.materialize_dynamics — Function
materialize_dynamics(dynamics_stub, grid, boundary_conditions, thermodynamic_constants, microphysics, formulation)

Materialize a dynamics stub into a complete dynamics object with all required fields.

The microphysics and formulation arguments select the parcel's prognostic state.

source
Breeze.AtmosphereModels.materialize_formulation — Function
materialize_formulation(formulation, dynamics, grid, boundary_conditions)

Materialize a thermodynamic formulation from a Symbol (or formulation struct) into a complete formulation with all required fields.

Valid symbols:

  • :LiquidIcePotentialTemperature, :θ, :ρθ, :PotentialTemperature → LiquidIcePotentialTemperatureFormulation
  • :StaticEnergy, :s, :ρs → StaticEnergyFormulation
source
Breeze.AtmosphereModels.materialize_microphysical_fields — Method
materialize_microphysical_fields(
    microphysics::Nothing,
    grid,
    boundary_conditions
) -> NamedTuple{(:qᵛ,), <:Tuple{Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}}}

Build microphysical fields associated with microphysics on grid and with user defined boundary_conditions.

source
Breeze.AtmosphereModels.materialize_sedimentation — Method
materialize_sedimentation(
    dynamics,
    microphysics,
    microphysical_fields,
    advection
) -> NamedTuple

Materialize the sedimenting condensates for the selected dynamics. Eulerian dynamics use the microphysics-only materializer by default.

source
Breeze.AtmosphereModels.materialize_sedimentation — Method
materialize_sedimentation(
    microphysics,
    microphysical_fields,
    advection
) -> NamedTuple

Return the NamedTuple of SedimentingCondensates of microphysics, keyed by prognostic name: one for every name in condensate_field_names with a sedimentation_velocity, holding that velocity field, the specific-humidity field, the prognostic partial density it is diagnosed from, its condensate_liquid_fraction, and the advection scheme that transports the tracer's mass. Condensate that does not sediment (for example, cloud condensate diagnosed by saturation adjustment) is absent: it moves no mass and therefore no latent heat. The result is the empty (;) when nothing sediments, including for Nothing microphysics.

Throws an ArgumentError if a sedimenting condensate mass declares no liquid fraction.

source
Breeze.AtmosphereModels.maybe_adjust_thermodynamic_state — Method
maybe_adjust_thermodynamic_state(
    state,
    ::Nothing,
    qᵛ,
    constants
)

Possibly apply saturation adjustment. If a microphysics scheme does not invoke saturation adjustment, just return the state unmodified.

The arguments are the thermodynamic state, microphysics scheme, prognostic specific moisture, and thermodynamic constants. The six-argument form also receives the density-weighted microphysical prognostics and total density, so precipitation can be retained during adjustment. Non-equilibrium schemes return the state unchanged.

source
Breeze.AtmosphereModels.microphysics_model_update! — Method
microphysics_model_update!(microphysics::Nothing, model)

Apply the operator-split microphysics update for the given microphysics scheme.

This is called once per time step by the time-stepper (not from update_state!) to apply microphysics processes that operate on the full model state by the full Δt, rather than through the per-stage tendency interface. It runs after the time-stepper's update_state! has refreshed the diagnostic state it reads. Schemes that mutate prognostic fields here are responsible for restoring a consistent model state (halos, diagnostics, and tendencies) before returning — e.g. by calling update_state!. Defaults to a no-op; specific microphysics schemes extend this function.

source
Breeze.AtmosphereModels.overlying_atmosphere_faces — Method
overlying_atmosphere_faces(
    extension::OverlyingAtmosphereColumn{FT},
    z_top,
    Δz_top
) where FT -> Vector

The face heights of the extension layers of extension above a grid whose top face is at z_top and whose top layer is Δz_top thick: a vector of Nₑ + 1 heights starting at z_top and ending exactly at extension.top, with the first layer Δz_top thick and successive layers stretched by the geometric_stretching_ratio. Nₑ = extension.layers, or 0 (a single face at z_top) when the grid already reaches extension.top.

julia> using Breezejulia> using Breeze.AtmosphereModels: overlying_atmosphere_facesjulia> extension = OverlyingAtmosphereColumn(top = 3100, layers = 3);julia> overlying_atmosphere_faces(extension, 3000, 10)4-element Vector{Float64}: 3000.0 3010.0 3035.4138126514913 3100.0
source
Breeze.AtmosphereModels.postprocess_microphysical_prognostics — Method
postprocess_microphysical_prognostics(
    microphysics,
    prognostics,
    ρ
)

Restore scheme-specific constraints on density-weighted microphysical prognostics after a parcel time-integration substep.

The default returns prognostics unchanged. Schemes with coupled prognostic constraints may extend this hook to return a corrected value.

source
Breeze.AtmosphereModels.pressure_from_density_temperature — Method
pressure_from_density_temperature(
    i,
    j,
    k,
    grid,
    dynamics,
    ρ,
    T,
    q,
    constants
)

Return pressure consistent with a prescribed temperature during thermodynamic initialization.

The default retains dynamics_pressure (appropriate for anelastic/reference-pressure models, where pressure is not a function of the state being set). Compressible dynamics overrides this with the equation of state p = ρ Rᵐ T, avoiding a fixed-point error when density or composition was changed immediately before setting temperature.

source
Breeze.AtmosphereModels.prognostic_dynamics_field_names — Method
prognostic_dynamics_field_names(dynamics)

Return a tuple of prognostic field names specific to the dynamics formulation.

For anelastic dynamics, returns an empty tuple (no prognostic density). For compressible dynamics, returns (:ρᵈ,) for prognostic density.

source
Breeze.AtmosphereModels.prognostic_momentum_field_names — Method
prognostic_momentum_field_names(dynamics)

Return a tuple of prognostic momentum field names.

For prognostic dynamics (anelastic, compressible), returns (:ρu, :ρv, :ρw). For kinematic dynamics (prescribed velocities), returns an empty tuple.

source
Breeze.AtmosphereModels.refreshes_state_after_update — Method
refreshes_state_after_update(microphysics) -> Bool

Whether an operator-split microphysics update refreshes halos, diagnostics, and all tendencies before returning for a finite positive time step. Such schemes must not read the incoming tendencies. The time stepper may omit the preceding tendency pass only when no tendency callbacks would be lost. Defaults to false.

source
Breeze.AtmosphereModels.rescale_density_weighted_fields! — Method
rescale_density_weighted_fields!(model, ρ⁻)

Rescale all density-weighted prognostic fields so that specific quantities (velocity, potential temperature, moisture, etc.) are preserved after a change in the reference density ρᵣ. Each field is multiplied by ρᵣ_new / ρᵣ_old.

Momentum fields (ρu, ρv, ρw) live at staggered face locations and require interpolation of the cell-centered density; a dedicated kernel handles this. All other prognostic fields are cell-centered and rescaled with broadcasting.

source
Breeze.AtmosphereModels.reset_reference_state! — Method
reset_reference_state!(model)

Recompute the dynamics' reference state from the horizontal means of the model's current state via set_to_mean! — works for both the anelastic ReferenceState and the split-explicit ExnerReferenceState — if the dynamics carries one; a no-op otherwise. Invoked by set!(model; compute_reference_state=true).

source
Breeze.AtmosphereModels.resolve_surface_albedos — Method
resolve_surface_albedos(
    surface_albedo,
    direct_surface_albedo,
    diffuse_surface_albedo,
    grid,
    solar_position
) -> Tuple{Any, Any}

Resolve the albedo keywords of a RadiativeTransferModel constructor into a (direct, diffuse) pair of materialized surface albedos.

Either surface_albedo alone (used for both the direct and the diffuse albedo) or both direct_surface_albedo and diffuse_surface_albedo must be given; any other combination is an ArgumentError. Each is passed through materialize_surface_property with grid and solar_position.

source
Breeze.AtmosphereModels.sedimentation_mass_fluxes — Function

Return the vertical advective mass fluxes of humidity q through the lower and upper faces of cell (i, j, k), as ((F⁻(wᵗ + wˢ), F⁻(wᵗ)), (F⁺(wᵗ + wˢ), F⁺(wᵗ))): at each face, the flux at the combined velocity and at the resolved transport velocity wᵗ alone, both with the tracer's own advection scheme, integrated over the face area and per unit density [m³ s⁻¹]. Their difference is the sedimentation part of the mass flux the tracer tendency applies to the cell; sedimentation_tendency weights each with the content it delivers to the cell. The fluxes belong to the cell rather than to a face because bounds-preserving WENO limits its reconstructions cell by cell, so the flux through a face differs between the two cells that share it. Under adaptive implicit vertical advection these are the CFL-scaled explicit fluxes only; the first-order remainder the implicit solve applies is implicit_sedimentation_mass_fluxes.

Implemented in Breeze.Advection, which owns the flux operators.

source
Breeze.AtmosphereModels.sedimentation_tendency — Method
sedimentation_tendency(
    i,
    j,
    k,
    grid,
    condensates,
    wᵗ,
    formulation,
    dynamics,
    constants,
    microphysics,
    microphysical_fields,
    specific_prognostic_moisture,
    temperature
)

Return the tendency of the continuity-density-weighted thermodynamic variable (ρθ = ρᵈ θ or ρs = ρᵈ s) at cell (i, j, k) from the sedimentation of the condensate the condensates describe (see materialize_sedimentation): the part the tracer tendencies apply, which is the whole transport of an explicit scheme and the CFL-limited explicit fraction under adaptive implicit vertical advection (the remainder follows in implicit_sedimentation_step!). Callers add the result to their tendency. wᵗ is the vertical velocity the tracer tendencies transport the condensates with; the remaining arguments are those of condensate_content. Returns zero when no condensate sediments.

With V the cell volume, ρᶠ the total density at each face and ± the face's outward sign, the tendency is

−(ρᵈ / ρ) V⁻¹ Σ_faces ± ρᶠ Σᵢ [cᵢ(Wᵢ) Fᵢ(Wᵢ) − cᵢ(wᵗ) Fᵢ(wᵗ)] ,

where Fᵢ(w) is the vertical advective flux of condensate i's humidity at velocity w through the face with the scheme that transports the tracer (sedimentation_mass_fluxes), Wᵢ = wᵗ + wᵢ its total velocity, ρ the total_density that weights the tracer's mass flux, ρᵈ the continuity_density that carries the thermodynamic variable, and cᵢ(w) = χᵢ + (∂φ/∂h) (hᵢ(w) − hᵢ) the content the flux delivers to the cell: the cell's own χ of the condensate's phase, plus its ∂φ/∂h times the enthalpy in the upwind cell of w in excess of its own. A flux out drains the cell itself and delivers χ alone, changing the composition at fixed temperature; a flux in adds the cell's conversion of the sensible heat the arriving mass brings from another level. The tracer tendency advects each humidity at Wᵢ in place of wᵗ, so the bracket is the sedimentation part of the mass flux it applies to the cell, provided wᵗ is the velocity that tendency used: upwind selection and the adaptive implicit split are nonlinear in the velocity, so fluxes formed at another one would not recombine into the applied flux.

For s the delivered content is the upwind cell's h, so the tendency is the negative divergence of a face flux and ∫ρs is conserved. For θˡⁱ it is not: ∂θˡⁱ/∂qˣ varies with the Exner function, so transporting it between pressure levels would conserve ∫ρθ, which precipitation does not. The θˡⁱ tendency is a cell-local response, not the divergence of a unique conservative thermodynamic face flux. Continuity advances ρᵈ without a sedimentation source on every core, so the content moved per unit total mass is the change of the specific variable, and the cell's ratio ρᵈ / ρ (one on the anelastic core, the dry mass fraction on the compressible core) turns it into the change of the continuity-density-weighted prognostic.

source
Breeze.AtmosphereModels.set_default_aerosol_number! — Method
set_default_aerosol_number!(model)

Write the default aerosol reservoir initial_aerosol_number_density into ρnᵃ, using the total air density total_density of model. A no-op for schemes without prognostic aerosol.

Called at the end of AtmosphereModel construction, and again from every set! that does not supply nᵃ or ρnᵃ, so the reservoir is weighted by whichever density is established at the time: the reference density for anelastic dynamics, a prescribed density for the kinematic driver, the reconciled total density for compressible dynamics. Compressible density fields are zero at construction, so there the constructor writes zero and the first set! carrying ρ, ρᵈ, or a HydrostaticallyBalancedDensity fills it in.

Because this runs on every such set!, a later call that re-initializes the state also resets the reservoir to the distribution default. Pass nᵃ or ρnᵃ explicitly to carry a depleted reservoir across a set!.

source
Breeze.AtmosphereModels.set_hydrostatically_balanced_density! — Method
set_hydrostatically_balanced_density!(
    model,
    spec::HydrostaticallyBalancedDensity
)

Set the prognostic density of a CompressibleDynamics model into discrete hydrostatic balance with the current θˡⁱ/qᵛ, per HydrostaticallyBalancedDensity. Runs the same per-column Exner integration the reference-state constructor uses, then scales the dry density (and rescales the density-weighted prognostics, preserving θ, qˣ, and velocities) so the total density matches the balanced column.

source
Breeze.AtmosphereModels.settable_specific_microphysical_names — Method
settable_specific_microphysical_names(
    microphysics
) -> Tuple{Vararg{Symbol}}

Return a tuple of specific (non-density-weighted) names that can be set for the given microphysics scheme. These are derived from the prognostic field names by removing the 'ρ' prefix.

For mass fields (e.g., ρqᶜˡ → qᶜˡ), number fields (e.g., ρnᶜˡ → nᶜˡ), and volume fields (e.g., ρbᶠ → bᶠ).

source
Breeze.AtmosphereModels.skip_vertical_diffusion — Method
skip_vertical_diffusion(
    model::AtmosphereModel,
    name::Symbol
)

Whether the prognostic field name sits out the vertically-implicit solve. The dynamics-specific prognostics — the compressible dry density, the kinematic driver's density — are advanced explicitly and have no diffusivity to apply; momentum and every scalar take the solve.

source
Breeze.AtmosphereModels.slow_dynamics — Method
slow_dynamics(timestepper, dynamics)

Return the part of dynamics that timestepper integrates through its tendencies: all of it, unless the time stepper integrates the pressure-gradient force and buoyancy separately, in which case it returns SlowDynamics(dynamics).

source
Breeze.AtmosphereModels.specific_to_density_weighted — Method
specific_to_density_weighted(
    name::Symbol
) -> Union{Nothing, Symbol}

Convert a specific microphysical variable name to its density-weighted counterpart. For example, :qᶜˡ → :ρqᶜˡ, :qʳ → :ρqʳ, :nᶜˡ → :ρnᶜˡ, :bᶠ → :ρbᶠ.

Returns nothing if the name doesn't start with 'q', 'n', or 'b'. These are the mass, number, and volume prefixes; the set matches settable_specific_microphysical_names.

source
Breeze.AtmosphereModels.standard_specific_humidity — Method
standard_specific_humidity(z)

An idealized specific humidity (kg kg⁻¹) at height z (m): 10 g kg⁻¹ at the surface decaying with a 2.5 km scale height, floored at 3 mg kg⁻¹ (about 5 ppmv) for the dry stratosphere,

\[qᵛ(z) = max(10⁻² exp(-z / 2500 m), 3 × 10⁻⁶) .\]

julia> using Breeze.AtmosphereModels: standard_specific_humidityjulia> standard_specific_humidity(0)0.01julia> standard_specific_humidity(50e3)3.0e-6
source
Breeze.AtmosphereModels.surface_fraction_scalar — Method
surface_fraction_scalar(x::Number) -> Number

The scalar behind a surface property that is constant in space and time, or nothing when the property carries no such scalar.

A ConstantField is a scalar in a field's clothing — its value cannot change — so it reports the value it holds. A general Field reports nothing: it may be rewritten between radiation updates, so there is no single value to speak of.

source
Breeze.AtmosphereModels.surface_pressure — Function
surface_pressure(dynamics)

Return the pressure of the reference atmosphere at the bottom face of each column — the ground — obtained by reducing the base_pressure datum to that height along the reference profile, as a 2D $(Center, Center, Nothing)$ field. Horizontally uniform for a single-column reference on a height-coordinate grid; genuinely column-dependent when the reference thermodynamics varies horizontally or on a terrain-following grid, where the bottom face is the terrain surface.

This is the anchor for a hydrostatic column integration, and what every consumer of "the pressure at the surface" over terrain wants. Reading it keeps a consumer consistent with the reference state; reading the datum instead disagrees with it by $O(ρgh)$ per column.

Equal to the datum, exactly, for the usual domain whose bottom sits at $z = 0$. Extended by each dynamics that carries a materialized reference state; dynamics without one have no reference surface pressure to report. When the pressure should follow the live model state instead, extrapolate it from the first cell center with Thermodynamics.surface_pressure_from_cell_center, as the surface fluxes and the diagnostic hydrostatic pressure do.

source
Breeze.AtmosphereModels.thermodynamic_state_density — Method
thermodynamic_state_density(
    i,
    j,
    k,
    dynamics,
    T,
    q,
    constants
)

Return the density of the local thermodynamic state at (i, j, k), with temperature T and moisture mass fractions q. This is the density in the equation of state, $p = ρ Rᵐ T$, and the one the saturation specific humidity $qᵛ⁺ = pᵛ⁺ / (ρ Rᵛ T)$ is referenced to, so microphysics schemes and saturation diagnostics evaluate saturation with it.

It is the total density, condensate loading included: $Rᵐ(q) = qᵈ Rᵈ + qᵛ Rᵛ$ uses $qᵈ = 1 - qᵛ - qˡ - qⁱ$, so $p / (Rᵐ(q) T)$ is the total, not the gas-phase density $ρᵈ + ρᵛ$.

The default returns total_density, which is the state density on CompressibleDynamics. Dynamics closed on a reference or prescribed pressure (AnelasticDynamics, PrescribedDynamics) override it with fixed_pressure_state_density, $p / (Rᵐ T)$. On the anelastic core this differs from $total_density = ρᵣ$ wherever $T$ or $q$ depart from the reference state, and it is the density whose departure from $ρᵣ$ is the anelastic buoyancy.

source
Breeze.AtmosphereModels.thermodynamic_transport_velocities — Method
thermodynamic_transport_velocities(model)

Return the velocity tuple used for thermodynamic-variable advection: transport_velocities(model), unless the time stepper advects the thermodynamic variable with a different velocity than moisture and tracers.

source
Breeze.AtmosphereModels.top_face_pressure — Method
top_face_pressure(i, j, grid, p, ρ, g)

Pressure on the top face of column (i, j), extrapolated hydrostatically from the highest cell center: p_Nz - ρ_Nz g (z_{Nz+1}ᶠ - z_Nzᶜ).

source
Breeze.AtmosphereModels.total_condensate_density — Method
total_condensate_density(
    i,
    j,
    k,
    microphysics,
    moisture_density,
    microphysical_fields
)

Total condensate density $ρᵗ = ρqᵛᵉ + Σ ρqᶜ$ at (i, j, k): the moisture density $ρqᵛᵉ$ (vapor or equilibrium moisture) plus every condensed-species density named by condensate_field_names. Number-concentration fields (ρnˣ) are excluded. This sums all phases of the condensable species (water by default), so other condensates can be added by extending condensate_field_names.

source
Breeze.AtmosphereModels.update_cos_zenith! — Method
update_cos_zenith!(
    cos_zenith,
    ::FixedCosineZenith,
    grid,
    clock
)

Update the per-column cosine of the solar zenith angle in cos_zenith, dispatched on the solar-position specification:

Values are clamped to be non-negative (sun above the horizon).

source
Breeze.AtmosphereModels.update_exner_surface_state! — Method
update_exner_surface_state!(
    ref::ExnerReferenceState,
    θ,
    qᵛ,
    grid,
    constants,
    κ̂
)

Rewrite the bottom-face pressure and density of an ExnerReferenceState from the horizontal-mean near-surface state (θˢ, qᵛˢ), in place.

The datum is reduced with moist_hydrostatic_pressure — the same function the constructor anchors on — so a reset lands on the profile the constructor would have produced from this mean state. set_to_mean! is only reached on a height-coordinate grid, whose bottom face is a single level, so a horizontally uniform reduction is exact; terrain-following resets go through reset_reference_state!, which reduces the datum per column along the terrain.

source
Breeze.AtmosphereModels.update_radiation! — Method
update_radiation!(rtm, model)

Update the radiative fluxes of rtm from the current model state when they are due; the computation itself is _update_radiation!(rtm, model).

update_state! runs several times per time step: after each Runge-Kutta stage, and again after an operator-split update such as Kessler microphysics. Radiation is updated

  • at initialization: by every update_state! between steps at iteration 0 (clock.stage == 1), that is model construction, set! and the preparation of the first step, which all see the initial state;
  • during time stepping: once per iteration n > 0 at which rtm.schedule actuates, by the first-stage update_state! of the step that begins at n (the clock is then at stage 2 in Breeze's Runge-Kutta steppers). The new fluxes enter from the second stage of that step. Later stages, the end of the step and operator-split updates do not update radiation.

With schedule = IterationInterval(80) and Δt = 7.5 s, the fluxes are computed from the initial state and then every 600 s, in the steps that begin at iterations 80, 160, …

Under Reactant the iteration is traced: BreezeReactantExt applies the scheduled update with a traced conditional, which requires a stateless schedule such as IterationInterval, and computes the initial fluxes in Breeze.TimeSteppers.prepare_first_time_step! (also called by first_time_step!), which a traced window calls before its loop of time_step!.

source
Breeze.AtmosphereModels.validate_boundary_condition_names — Method
validate_boundary_condition_names(
    boundary_conditions,
    field_bc_names
)

Check that every key of the user-supplied boundary_conditions names something that can carry them: a prognostic field, a velocity component of dynamics whose velocities are prognostic, or one of the interface keys total_energy_density_name and total_moisture_density_name.

An unrecognized key would otherwise be merged in and then never looked up, so a stale one — ρe after the e → s rename, say — would silently materialize default no-flux conditions in place of the fluxes the caller asked for.

source
Breeze.AtmosphereModels.validate_microphysics — Method
validate_microphysics(microphysics, thermodynamic_constants)

Validate that microphysics is compatible with the model's thermodynamic_constants.

Defaults to a no-op. Schemes that require a particular thermodynamic formulation (for example a specific saturation vapor pressure formula) extend this method to throw a clear ArgumentError at model construction, rather than failing later inside a kernel — where the failure surfaces as an opaque dynamic getproperty / GPU compilation error.

source
Breeze.AtmosphereModels.validate_microphysics_architecture — Method
validate_microphysics_architecture(microphysics, arch)

Validate that microphysics can run on architecture arch; a no-op by default. Extensions throw an ArgumentError at model construction for schemes that need settings an architecture requires (for example a static sedimentation substep bound under Reactant).

source
Breeze.AtmosphereModels.validate_particles — Method
validate_particles(particles, grid)

Return particles unchanged. Extended for grids on which Lagrangian particle tracking is not supported, so that the combination is rejected at construction rather than producing wrong trajectories at run time (see TerrainFollowingDiscretization/lagrangian_particles.jl).

source
Breeze.AtmosphereModels.validate_surface_fractions — Method
validate_surface_fractions(; kw...)

Throw an ArgumentError for any keyword whose value is a spatially uniform scalar outside $[0, 1]$.

Emissivity and albedo are fractions, so a scalar outside the unit interval is a user error — an albedo given in percent, say — worth rejecting at construction rather than carrying into the solver. A property with no single value (a Field, a dataset, nothing) passes through, since a check at construction says nothing about what it holds at the next solve.

source
Breeze.AtmosphereModels.validate_velocity_boundary_conditions — Method
validate_velocity_boundary_conditions(
    dynamics,
    user_boundary_conditions
)

Validate that velocity boundary conditions are only provided for dynamics that support them.

By default, throws an error if the user provides boundary conditions for :u, :v, or :w, since velocity is a diagnostic field for most dynamics (e.g., anelastic, compressible).

For PrescribedDynamics, velocity boundary conditions are allowed since velocities are regular fields that can be set directly.

source
Breeze.AtmosphereModels.velocity_boundary_condition_names — Method
velocity_boundary_condition_names(dynamics)

Return a tuple of velocity field names that need default boundary conditions.

For most dynamics (anelastic, compressible), velocities are diagnostic and their boundary conditions are created internally. Returns an empty tuple.

For PrescribedDynamics, velocities are regular fields that can have user-provided boundary conditions, so this returns (:u, :v, :w).

source
Breeze.AtmosphereModels.with_thermodynamic_density — Function
with_thermodynamic_density(formulation, ρᵡ)

Return a copy of formulation whose thermodynamic density field (see thermodynamic_density) is replaced by ρᵡ, leaving the diagnostic fields and solvers untouched. Used to swap in a thermodynamic field carrying different boundary conditions without reallocating the diagnostics.

source
Breeze.AtmosphereModels.wrap_specific_forcing — Function
wrap_specific_forcing(value, density_name)

Wrap value so that the kernel-time density factor ρ is applied automatically when the user supplies a forcing keyed by a specific (per-unit-mass) variable name like θ, u, qᵉ. Implemented in the Forcings module: constructs a SpecificForcing, recurses into tuples, and errors if value is itself a density-tendency forcing like SubsidenceForcing (which would double-count ρ).

density_name is the corresponding density-weighted prognostic name (e.g. :ρθ) used to produce a helpful error message when the wrap is rejected.

source
Breeze.AtmosphereModels.x_pressure_gradient — Method
x_pressure_gradient(i, j, k, grid, dynamics)

Return the x-component of the pressure gradient force at (Face, Center, Center).

For anelastic dynamics, returns zero (pressure is handled via projection). For compressible dynamics, returns -∂p/∂x.

source
Breeze.AtmosphereModels.y_pressure_gradient — Method
y_pressure_gradient(i, j, k, grid, dynamics)

Return the y-component of the pressure gradient force at (Center, Face, Center).

For anelastic dynamics, returns zero (pressure is handled via projection). For compressible dynamics, returns -∂p/∂y.

source
Breeze.AtmosphereModels.z_pressure_gradient — Method
z_pressure_gradient(i, j, k, grid, dynamics)

Return the z-component of the pressure gradient force at (Center, Center, Face).

For anelastic dynamics, returns zero (pressure is handled via projection). For compressible dynamics, returns -∂p/∂z.

source
Breeze.AtmosphereModels.∇_dot_Jᶜ — Method
∇_dot_Jᶜ(i, j, k, grid, ρ, closure::AbstractTurbulenceClosure, closure_fields,
         id, c, clock, model_fields, buoyancy)

Return the discrete divergence of the dynamic scalar flux Jᶜ = ρ jᶜ, where jᶜ is the "kinematic scalar flux", using area-weighted differences divided by cell volume. Similar to Oceananigans' ∇_dot_qᶜ signature with the additional density factor ρ, where in Oceananigans qᶜ is the kinematic tracer flux.

source
Breeze.Thermodynamics.compute_reference_state! — Function
compute_reference_state!(
    model::AtmosphereModel,
    T̄,
    q̄ᵛ,
    q̄ˡ=0,
    q̄ⁱ=0
)

Recompute the reference state of model's dynamics from the temperature T̄ and the vapor, liquid and ice mass fractions q̄ᵛ, q̄ˡ, q̄ⁱ (Numbers, Function(z)s, or Fields), and update the pressure solver to the new reference density.

source
Oceananigans.BuoyancyFormulations.∂z_b — Method
∂z_b(
    i,
    j,
    k,
    grid,
    b::Breeze.AtmosphereModels.AtmosphereModelBuoyancy,
    tracers
)

The static stability $N² = g ∂_z \ln θᵨ$ at (Center, Center, Face), the vertical gradient of the buoyancy $b = -g ρ′ / ρᵣ$ that the dynamics uses, written through the density potential temperature density_potential_temperature so that condensate loading is included. The logarithm is differentiated, $∂_z \ln θᵨ = ∂_z θᵨ / θᵨ$, to keep the derivative and its denominator at consistent grid locations.

source
Oceananigans.Fields.set! — Method
set!(
    model::AtmosphereModel;
    time=nothing,
    enforce_mass_conservation=true,
    compute_reference_state=false,
    balancer=false,
    kw...
)

Set variables in an AtmosphereModel.

Keyword Arguments

Variables are set via keyword arguments. Supported variables include:

Prognostic variables (density-weighted):

  • ρ/ρᵈ: total / dry density (compressible). ρ may also be set to HydrostaticallyBalancedDensity(), which derives the density from the just-set θˡⁱ/qᵛ so the initial column is in discrete hydrostatic balance.
  • ρu, ρv, ρw: momentum components
  • ρqᵉ/ρqᵛ/ρqᵗ: moisture density (scheme-dependent)
  • Prognostic microphysical variables
  • Prognostic user-specified tracer fields

Settable thermodynamic variables:

  • T: in-situ temperature
  • θ: potential temperature
  • θˡⁱ: liquid-ice potential temperature
  • s: static energy
  • ρθ: potential temperature density
  • ρθˡⁱ: liquid-ice potential temperature density
  • ρs: static energy density (for StaticEnergyThermodynamics)

Diagnostic variables (specific, i.e., per unit mass):

  • u, v, w: velocity components (sets both velocity and momentum)
  • qᵗ: total specific moisture (sets both specific and density-weighted moisture)
  • ℋ: relative humidity (sets total moisture via qᵗ = ℋ * qᵛ⁺, where qᵛ⁺ is the saturation specific humidity at the current temperature). Relative humidity is in the range [0, 1]. For models with saturation adjustment microphysics, ℋ > 1 throws an error since the saturation adjustment would immediately reduce it to 1.

Specific microphysical variables (automatically converted to density-weighted):

  • qᶜˡ: specific cloud liquid, sets ρqᶜˡ = ρᵣ * qᶜˡ
  • qʳ: specific rain, sets ρqʳ = ρᵣ * qʳ
  • nᶜˡ: specific cloud liquid number [1/kg], sets ρnᶜˡ = ρᵣ * nᶜˡ
  • nʳ: specific rain number [1/kg], sets ρnʳ = ρᵣ * nʳ
  • bᶠ: specific rime volume [m³/kg], sets ρbᶠ = ρᵣ * bᶠ. P3 needs this alongside qᶠ: rime mass with no rime volume has no defined rime density and is discarded.
  • Other prognostic microphysical mass, number, and volume variables with the ρ prefix removed
The meaning of `θ`

When using set!(model, θ=...), the value is interpreted as the liquid-ice potential temperature $θˡⁱ$.

Options

  • enforce_mass_conservation: If true (default), applies a pressure correction to ensure the velocity field satisfies the anelastic continuity equation. If balancer is also used, a final correction is applied after the balance.

  • compute_reference_state: If true (default false), recompute the dynamics' hydrostatic reference state from the horizontal means of the just-set state (see set_to_mean!), before the mass-conservation correction. A no-op for dynamics without a reference state. Useful when initializing from an analysis whose mean profile should define the perturbation base state; otherwise the reference built at construction is preserved. For compressible dynamics, supply both a density and a thermodynamic variable in the same set! call, since the recomputation integrates the hydrostatic column from the model's current state.

  • balancer: adiabatic (FV3 na_init) spin-up of the nonhydrostatic state, run in place after the rest of set! — equivalent to calling balance_adiabatically!(model, balancer). false (default) does nothing; true uses AdiabaticBalancer() (auto step size); pass an AdiabaticBalancer to control Δt, cycles, weight, with_moisture, and (compressible) time_stepping. The balance runs on a stripped twin that shares all field memory with model (no second field set, no graft). Works for both CompressibleDynamics and AnelasticDynamics.

source

AtmosphereModels.Diagnostics

Breeze.AtmosphereModels.Diagnostics.saturation_total_specific_moisture — Method
saturation_total_specific_moisture(T, p, constants, surface)

Compute the saturation total specific moisture under the assumption that all moisture is vapor at saturation, $qᵗ = qᵛ⁺$. With this assumption, the equation of state for moist air can be solved in closed form, yielding an expression for the saturation specific humidity in terms of temperature T and pressure p alone:

\[qᵛ⁺ = \frac{ϵᵈᵛ \, pᵛ⁺(T)}{p + δᵈᵛ \, pᵛ⁺(T)} ,\]

where $ϵᵈᵛ ≡ Rᵈ / Rᵛ ≈ 0.622$ and $δᵈᵛ ≡ ϵᵈᵛ - 1 ≈ -0.378$.

The resulting expression coincides with the saturation specific humidity used in the COARE 3.6 Edson (2013) air-sea bulk-flux algorithms, where the air-side specific humidity at the surface is unknown a priori and saturation_specific_humidity cannot be evaluated directly.

See the Atmosphere Thermodynamics section of the documentation for a derivation.

source

BoundaryConditions

Breeze.BoundaryConditions.NearWallVirtualPotentialTemperature — Type
NearWallVirtualPotentialTemperature{M, N, FT, TC}(
    microphysics,
    specific_moisture_name,
    standard_pressure,
    thermodynamic_constants
) where {M, N, FT, TC} -> Breeze.BoundaryConditions.NearWallVirtualPotentialTemperature
NearWallVirtualPotentialTemperature(
    microphysics::M,
    specific_moisture_name::N,
    standard_pressure::FT,
    thermodynamic_constants::TC
) where {M, N, FT, TC} -> Breeze.BoundaryConditions.NearWallVirtualPotentialTemperature

The virtual potential temperature a stability-dependent bulk boundary condition compares against its surface value, evaluated from the model field tuple the boundary-condition kernel is handed rather than from fields captured at construction.

Boundary conditions are materialized before the dynamics is, so there are no model fields to capture at that point; deferring the read is what lets a compressible model's stability correction follow its prognostic pressure and density. The T entry comes from AtmosphereModels.auxiliary_model_fields and the p and ρ entries from AtmosphereModels.dynamics_thermodynamic_fields, which the caller has merged into one tuple by this point, so this reads the same thermodynamic pressure the rest of the model does: prognostic under CompressibleDynamics, the hydrostatic reference profile under AnelasticDynamics.

source
Breeze.AtmosphereModels.materialize_atmosphere_model_boundary_conditions — Function
materialize_atmosphere_model_boundary_conditions(
    boundary_conditions,
    grid,
    formulation,
    dynamics,
    microphysics,
    thermodynamic_constants,
    closure=nothing
) -> NamedTuple

Regularize boundary conditions for AtmosphereModel. This function walks through all boundary conditions and calls materialize_atmosphere_boundary_condition on each one, allowing specialized handling for bulk flux boundary conditions and other atmosphere-specific boundary condition types. The turbulence closure sets the gustiness of bulk fluxes constructed without one (see materialize_gustiness).

Boundary conditions supplied under an interface key are first routed onto the prognostic field that carries them: the energy key ρE onto the thermodynamic variable of formulation by convert_energy_bcs, and the moisture key ρqᵗ onto the moisture density of microphysics by convert_moisture_bcs.

source
Breeze.BoundaryConditions.bulk_richardson_number — Method
bulk_richardson_number(h, θᵥ, θᵥˢ, U, U_min, g)

Compute bulk Richardson number:

\[Riᴮ = (g / θ̄ᵥ) h (θᵥ - θᵥˢ) / U²\]

Wind speed is clamped to U_min to avoid singularity.

Arguments

  • h: Measurement height (m)
  • θᵥ: Virtual potential temperature at measurement height (K)
  • θᵥˢ: Virtual potential temperature at surface (K)
  • U: Wind speed (m/s)
  • U_min: Minimum wind speed (m/s)
  • g: Gravitational acceleration (m/s²)
source
Breeze.BoundaryConditions.convert_energy_bcs — Method
convert_energy_bcs(bcs, formulation) -> NamedTuple

Assemble the boundary conditions of the prognostic thermodynamic density of formulation: move any conditions supplied under the energy key ρE (see total_energy_density_name) onto it, converting the energy flux as that variable requires, and tell any bulk sensible-heat flux which surface difference to form. The ρE entry is dropped — it names an interface, not a field.

source
Breeze.BoundaryConditions.convert_moisture_bcs — Method
convert_moisture_bcs(bcs, microphysics) -> NamedTuple

Assemble the boundary conditions of the prognostic moisture density of microphysics, moving any conditions supplied under the moisture key ρqᵗ (see total_moisture_density_name) onto it. Water enters that variable unconverted whatever the scheme calls it, so unlike the energy key this is a pure re-key. The ρqᵗ entry is dropped — it names an interface, not a field.

source
Breeze.BoundaryConditions.initialize_Δθᵥ! — Method
initialize_Δθᵥ!(
    fv::FilteredSurfaceVelocities,
    coef,
    Tˢ,
    grid,
    clock,
    fields
)

Set the filtered surface-layer virtual potential temperature difference to its current value, formed by the bulk coefficient coef from the first-cell state and the surface temperature Tˢ (a number, a field on the bottom, or a function of the wall coordinates and time, evaluated at clock.time).

fields is the surface-layer field tuple (surface_layer_state); it is mandatory rather than defaulted, because the instantaneous θᵥ diagnostic evaluates itself from it and a kernel cannot report a useful error when it is missing.

source
Breeze.BoundaryConditions.materialize_gustiness — Method
materialize_gustiness(gustiness, closure)

Return the gustiness a bulk-flux boundary condition uses in a model with turbulence closure. A DefaultGustiness placeholder becomes a TKEGustiness under a TKEBasedTurbulenceClosure (a method the TurbulenceClosures module adds) and a constant gustiness of zero under any other closure, or none; a gustiness that was given, a number or a TKEGustiness, is returned unchanged.

using Breezeusing Breeze.BoundaryConditions: DefaultGustiness, materialize_gustinessmaterialize_gustiness(DefaultGustiness(), TKEBasedTurbulenceClosure())# outputTKEGustiness{Float64}(coefficient=0.816497, minimum=0.5)
source
Breeze.BoundaryConditions.neutral_coefficient_10m — Method
neutral_coefficient_10m(polynomial, U₁₀, U_min)

Compute neutral transfer coefficient at 10 m using the Large and Yeager (2009) form:

\[C^N_{10}(U) = a_0 + a_1 U + a_2 / U\]

Wind speed is clamped to U_min to avoid singularity in the $a_2/U$ term.

References

  • Large, W., & Yeager, S. G. (2009). The global climatology of an interannually varying air–sea flux data set. Climate dynamics, 33(2), 341-364.
source
Breeze.BoundaryConditions.surface_layer_state — Method
surface_layer_state(model_fields, dynamics_fields)

The field tuple the wall diagnostics read: the model fields merged with the thermodynamic pressure p and density ρ.

Those two arrive separately, in the tuple boundary_condition_args passes after the model fields, because under AnelasticDynamics they are dimension-reduced fields. Admitting them to Oceananigans.fields(model) would make the positional lookup that user forcings and boundary functions perform on it non-concrete, and the GPU compiler then rejects every kernel that performs one — see AtmosphereModels.dynamics_thermodynamic_fields. Merging the two here is resolved at compile time, and everything downstream reads its fields by name, which stays type-stable however heterogeneous the merged tuple is.

The single-argument method assembles the same tuple from a model, for host-side callers: the filtered Δθᵥ update and the tests.

source
Breeze.BoundaryConditions.wall_virtual_potential_temperature — Function
wall_virtual_potential_temperature(
    Tˢ,
    pˢ,
    pˢᵗ,
    constants,
    surface,
    β=1,
    qᵛ=0
)

Compute the virtual potential temperature of a planar surface with surface temperature Tˢ, surface pressure pˢ, standard pressure pˢᵗ, moisture availability β and first-cell specific humidity qᵛ,

\[θᵥˢ = \frac{Tˢ}{Πᵈˢ} (1 + δᵛᵈ qˢ), \qquad qˢ = β qᵛ⁺ + (1 - β) qᵛ, \qquad Πᵈˢ = (pˢ / pˢᵗ)^{Rᵈ/cᵖᵈ}\]

where $qᵛ⁺$ is the saturation specific humidity at the surface and $δᵛᵈ = Rᵛ/Rᵈ - 1$ (≈ 0.608 for water vapor in Earth's atmosphere; the actual value depends on the gas constants in constants). A saturated surface ($β = 1$, the default) carries its saturation humidity; a dry surface ($β = 0$) carries the humidity of the air above it, and so contributes no moisture of its own to the surface buoyancy. The dry Exner factor is required because the stability difference compares two virtual potential temperatures, not virtual temperature at the surface against potential temperature aloft.

source
Breeze.BoundaryConditions.wall_virtual_potential_temperature — Method
wall_virtual_potential_temperature(
    i,
    j,
    k,
    coef::PolynomialCoefficient,
    Tˢ,
    fields,
    pˢ
)

The virtual potential temperature of the wall next to the cell (i, j, k), from the wall temperature Tˢ, the air pressure pˢ at the wall, and the coefficient's standard pressure, constants, surface phase and moisture availability, together with the specific humidity of the air in the near-wall cell.

source

CelestialMechanics

CompressibleEquations

Breeze.AtmosphereModels.buoyancy_forceᶜᶜᶜ — Method
buoyancy_forceᶜᶜᶜ(
    i,
    j,
    k,
    grid,
    dynamics::CompressibleDynamics,
    temperature,
    specific_prognostic_moisture,
    microphysics,
    microphysical_fields,
    constants
)

Compute the buoyancy force density for compressible dynamics at cell center (i, j, k).

When a reference state is provided, the buoyancy force is computed as a perturbation:

\[ρ b = -g (ρ - ρ_r)\]

where $ρ_r$ is the reference density in discrete hydrostatic balance. This eliminates the $O(Δz^2)$ truncation error from the near-cancellation of $∂p/∂z$ and $gρ$, which is essential for stability with acoustic substepping at large time steps.

Without a reference state, the full gravitational force $-gρ$ is used.

source
Breeze.AtmosphereModels.compute_auxiliary_dynamics_variables! — Method
compute_auxiliary_dynamics_variables!(
    model::AtmosphereModel{<:CompressibleDynamics}
)

Compute temperature and pressure jointly for CompressibleModel.

For compressible dynamics with potential temperature thermodynamics, temperature and pressure are coupled via the ideal gas law and the potential temperature definition:

\[θ = T (p₀/p)^κ \quad \text{and} \quad p = ρ R^m T\]

Eliminating the circular dependency gives the direct formula:

\[T = θ^γ \left(\frac{ρ R^m}{p₀}\right)^{γ-1}\]

where $γ = c_p / c_v$ is the heat capacity ratio. Once temperature is known, pressure is computed from the ideal gas law $p = ρ R^m T$.

This joint computation is necessary because, unlike anelastic dynamics where pressure comes from a reference state, compressible dynamics requires solving for both temperature and pressure simultaneously.

source
Breeze.AtmosphereModels.default_drag_surface_temperature — Method
default_drag_surface_temperature(
    ::CompressibleDynamics,
    grid,
    constants
)

BulkDrag under CompressibleDynamics requires the user to supply surface_temperature explicitly. Unlike AnelasticDynamics, compressible dynamics does not carry a reference profile from which a surface temperature can be unambiguously derived. A clean default requires coupling to a surface model or an explicitly prescribed surface temperature.

source
Breeze.AtmosphereModels.surface_pressure — Method
surface_pressure(dynamics::CompressibleDynamics)

Return the reference pressure at the bottom face of each column, as a 2D field. Requires a materialized reference state: with reference_state = nothing there is no reference atmosphere whose ground pressure could be reported.

source
Breeze.CompressibleEquations.convert_acoustic_parameter — Method

Split-explicit time discretization for compressible dynamics.

Outer integration is the Wicker–Skamarock RK3 scheme (Wicker and Skamarock 2002) with stage fractions $β = (1/3, 1/2, 1)$. Within each stage, an inner substep loop evolves linearized acoustic perturbations about each RK stage-entry state. The vertically implicit solve uses an off-centered Crank-Nicolson scheme with off-centering parameter $\omega$ (default 0.65; $\omega = 0.5$ is classic centered CN).

The substep distribution across stages is selectable via the AcousticSubstepDistribution interface.

Fields

  • substeps: Number of acoustic substeps $N$ per outer $Δt$. Default nothing adaptively chooses $N$ from the horizontal acoustic CFL each step (see acoustic_cfl).

  • acoustic_cfl: Target horizontal acoustic Courant number used by the adaptive substep count when substeps === nothing. The substep count is $N \approx \lceil \Delta t \, c^{ac} / (\mathrm{acoustic\_cfl} \cdot \Delta x_\min) \rceil$, so smaller values give more substeps. Default 0.5 (the ERF/WRF target — equivalent to the conventional safety factor of 2). Ignored when substeps is set explicitly.

  • forward_weight: Off-centering parameter $\omega$ for the vertically implicit solve. $\omega = 0.5$ is classic centered Crank-Nicolson; the default $\omega = 0.65$ adds modest off-centering ($\varepsilon = 2\omega - 1 = 0.3$). Combined with the default divergence damping, it keeps a rest atmosphere at machine ε at production $\Delta t = 20$ s and survives the DCMIP-2016 dry/moist baroclinic-wave smoke tests at production grid.

    Note on residual non-normality: the column tridiag has anti-symmetric buoyancy off-diagonals (gravity-wave physics) and asymmetric PGF off-diagonals on a stratified $\bar\theta(z)$, so the substep operator $U$ has spectral radius $\rho(U) = 1$ but operator norm $\|U\|_2 \gg 1$ (≈ 44 at $\Delta t = 20$ s, $\omega = 0.55$, no damping). Perturbations can transiently project onto the non-normal amplified subspace. The stage-rewind formulation keeps the exact discrete rest atmosphere bounded even without divergence damping, while the default off-centering plus Klemp horizontal divergence damping damps acoustic noise in production baroclinic-wave and LES runs.

  • damping: Acoustic divergence damping strategy. Default: ThermalDivergenceDamping with coefficient 0.1. The exact discrete rest atmosphere is covered by test/substepper_rest_state.jl even with NoDivergenceDamping, but noisy acoustic production cases use damping to control grid-scale divergent modes.

  • sponge: Optional UpperSponge that applies implicit Rayleigh damping to $(ρw)′$ inside the substep loop's column tridiag, absorbing acoustic / gravity-wave energy in a layer below the rigid lid. Default nothing (off). Passing UpperSponge(; ...) enables it with the configured damping_rate and depth.

  • substep_distribution: How acoustic substeps are distributed across the three WS-RK3 stages.

  • open_boundary_relaxation: Per-substep relaxation factor $α \in (0, 1]$ applied at the outermost open-boundary cell of $ρ′,(ρθ)′$ to enforce the prescribed wall value across the acoustic substeps. Default $α = 0.5$, matching FV3-LAM's outermost-blend-row weight ($\approx 0.6$). Without this enforcement the perturbation halos reflect, biasing the discrete mass balance under transient open-boundary inflow (issue #738). The relaxation is a no-op when no side carries an active open BC (periodic, walls, impenetrable defaults all skip it).

Backward integration

Backward integration (Δt < 0) is supported. The off-centered Crank–Nicolson vertical solve with $ω ∈ [0.5, 1]$ has amplification factor $|A|^2 = (1 + ((1-ω) ω_0 Δτ)^2) / (1 + (ω ω_0 Δτ)^2) \le 1$ for either sign of $Δτ$, so the linearized acoustic substep is A-stable in both directions. Horizontal divergence damping is sign-self-consistent ($γ \propto Δτ^{-1}$ and $(ρθ)' - (ρθ)'_\mathrm{old} \propto Δτ$ both flip sign with Δt). The adaptive substep count uses $|Δt|$, and the optional UpperSponge keeps its dissipative sign so it acts as a one-sided regularizer in both directions (i.e. backward integration through a sponge layer is stable but not an exact inverse of the forward step inside the sponge).

See also ExplicitTimeStepping.

source
Breeze.CompressibleEquations.with_time_discretization — Method
with_time_discretization(
    dynamics::CompressibleDynamics,
    time_discretization
) -> CompressibleDynamics

Return a CompressibleDynamics identical to dynamics but with its time_discretization replaced. Every field (densities, pressure, reference and terrain states) is shared by reference — only the immutable scheme wrapper changes — so this allocates no field memory. Used to build the adiabatic-balance twin (an ExplicitTimeStepping view of a production model).

source
Breeze.CompressibleEquations.without_sponge — Method
without_sponge(time_discretization)

Return a copy of time_discretization with its upper sponge removed. The adiabatic-balance excursion must be reversible, and the sponge (like divergence damping) is an irreversible term; balance_adiabatically! therefore requires a sponge-free model. No-op for discretizations that carry no sponge (e.g. ExplicitTimeStepping).

source

Forcings

KinematicDriver

Microphysics

Breeze.Microphysics.NumberConcentrationKernelFunction — Type
NumberConcentrationKernelFunction{P, M, Q, R}

Kernel callable for the lazy total number concentration $ρnˣ$ (m⁻³) of a one-moment microphysics species, computed from the prognostic mass density $ρqˣ$ and the species' assumed Marshall–Palmer size distribution as $ρnˣ = n_0 \, λ^{-1}$.

Fields

  • pdf: size distribution (ParticlePDFIceRain or ParticlePDFSnow)
  • mass: mass(radius) parameters (ParticleMass)
  • ρq: prognostic mass density field for the species [kg/m³]
  • reference_density: air density field [kg/m³]
source
Breeze.AtmosphereModels.bottom_precipitation_flux — Method
bottom_precipitation_flux(
    model,
    ::Breeze.Microphysics.DCMIP2016KesslerMicrophysics
) -> Field{LX, LY, LZ, O, G, I, D, T, B, Oceananigans.Fields.FieldStatus{Float64}} where {LX, LY, LZ, O, G, I, D, T, B}

Return the bottom precipitation flux field for the DCMIP2016 Kessler microphysics scheme.

The bottom precipitation flux is the substep-mean $ρ^r v^t_{rain}$ at the lowest face. The stored precipitation rate is normalized so multiplying it by the final total density recovers this mass flux exactly. Units are kg/m²/s.

This implements the Breeze bottom_precipitation_flux(model) interface.

source
Breeze.AtmosphereModels.bottom_precipitation_flux — Method
bottom_precipitation_flux(
    model,
    ::InstantaneousPrecipitation
) -> Field{LX, LY, LZ, O, G, I, D, T, B, Oceananigans.Fields.FieldStatus{Float64}} where {LX, LY, LZ, O, G, I, D, T, B}

Return the bottom precipitation flux for the instantaneous-precipitation scheme.

The scheme removes condensed water immediately, so the flux is the column integral of the volumetric precipitation rate. Units are kg/m²/s.

source
Breeze.AtmosphereModels.materialize_microphysical_fields — Method
materialize_microphysical_fields(
    ::Breeze.Microphysics.DCMIP2016KesslerMicrophysics,
    grid,
    boundary_conditions
) -> NamedTuple{(:ρqᶜˡ, :ρqʳ, :qᵛ, :qᶜˡ, :qʳ, :precipitation_rate, :𝕎ʳ, :sedimentation_substeps), <:Tuple{Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}, Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}}}

Create and return the microphysical fields for the Kessler scheme.

Prognostic Fields (Density-Weighted)

  • ρqᶜˡ: Density-weighted cloud liquid mass fraction.
  • ρqʳ: Density-weighted rain mass fraction.

Diagnostic Fields (Mass Fractions)

  • qᵛ: Water vapor mass fraction, diagnosed as $q^v = q^t - q^{cl} - q^r$.
  • qᶜˡ: Cloud liquid mass fraction (kg/kg).
  • qʳ: Rain mass fraction (kg/kg).
  • precipitation_rate: Surface precipitation rate (m/s), obtained by normalizing the substep-mean rain mass flux by the final surface air density.
  • 𝕎ʳ: Rain terminal velocity (m/s).
  • sedimentation_substeps: The largest number of sedimentation substeps each column has needed since the model was built (see maximum_sedimentation_substeps).
source
Breeze.AtmosphereModels.microphysics_model_update! — Method
microphysics_model_update!(
    microphysics::Breeze.Microphysics.DCMIP2016KesslerMicrophysics,
    model
)

Apply the Kessler microphysics to the model.

This function launches a kernel that processes each column independently, with rain sedimentation subcycling.

The kernel handles conversion between mass fractions and mixing ratios internally for efficiency. Water vapor is diagnosed from $q^v = q^t - q^{cl} - q^r$.

The kernel writes prognostic fields in the interior only, so update_state! is called afterwards to restore a consistent model state (halos, diagnostics, and tendencies).

source
Breeze.AtmosphereModels.microphysics_model_update! — Method
microphysics_model_update!(
    microphysics::Breeze.Microphysics.DCMIP2016KesslerMicrophysics,
    model::AtmosphereModel{<:ParcelDynamics}
)

Apply DCMIP2016 Kessler microphysics to a parcel model.

For a Lagrangian parcel, the microphysics processes are:

  1. Autoconversion: Cloud water → rain when cloud exceeds threshold
  2. Accretion: Rain + cloud → rain (collection)
  3. Saturation adjustment: Vapor ↔ cloud to maintain equilibrium
  4. Rain evaporation: Rain → vapor in subsaturated air

Note: Rain sedimentation is not applicable to a Lagrangian parcel since the parcel is a closed system (rain does not fall out of the parcel).

source
Breeze.AtmosphereModels.precipitation_rate — Method
precipitation_rate(
    model,
    ::Breeze.Microphysics.DCMIP2016KesslerMicrophysics,
    ::Val{:liquid}
)

Return the liquid precipitation rate field for the DCMIP2016 Kessler microphysics scheme.

The precipitation rate is computed internally by the Kessler kernel and stored in μ.precipitation_rate. The kernel time-averages the rain mass flux across sedimentation substeps and normalizes it by the final surface air density. For a fixed-density column this reduces to $q^r v^t_{rain}$, matching the one-moment microphysics definition. Units are m/s.

This implements the Breeze precipitation_rate(model, phase) interface, allowing the DCMIP2016 Kessler scheme to integrate with Breeze's standard diagnostics.

source
Breeze.Microphysics.cloud_to_rain_production — Method
cloud_to_rain_production(rᶜˡ, rʳ, Δt, microphysics)

Compute cloud-to-rain production rate from autoconversion and accretion (Klemp and Wilhelmson 1978, eq. 2.13).

This implements the combined effect of:

  • Autoconversion: Cloud water spontaneously converting to rain when rᶜˡ > rᶜˡ★
  • Accretion: Rain collecting cloud water as it falls

The formula uses an implicit time integration for numerical stability.

References

  • Klemp, J. B., & Wilhelmson, R. B. (1978). The simulation of three-dimensional convective storm dynamics. Journal of the Atmospheric Sciences, 35(6), 1070-1096.
source
Breeze.Microphysics.condensation_rate — Method
condensation_rate(qᵛ, qᵛ⁺, qᶜˡ, T, 𝒰, τᶜˡ, constants)

Compute the condensation/evaporation rate for cloud liquid water in a relaxation-to-saturation model.

This returns the rate of change of cloud liquid mass fraction (kg/kg/s). Positive values indicate condensation; negative values indicate evaporation. Evaporation is limited by the available cloud liquid.

source
Breeze.Microphysics.deposition_rate — Method
deposition_rate(qᵛ, qᵛ⁺ⁱ, qᶜⁱ, T, 𝒰, τᶜⁱ, constants)

Compute the deposition/sublimation rate for cloud ice in a relaxation-to-saturation model.

This returns the rate of change of cloud ice mass fraction (kg/kg/s). Positive values indicate deposition; negative values indicate sublimation. Sublimation is limited by the available cloud ice.

source
Breeze.Microphysics.sedimentation_substeps — Method
sedimentation_substeps(
    Δt,
    max_Δt,
    substep_limit
) -> Tuple{Any, Any, Any}

The sedimentation substeps for a step Δt whose rain CFL limit is max_Δt, validated before the count becomes an integer. The ratio Δt / max_Δt must be finite and positive, and the count needed, max(1, ceil(Δt / max_Δt)), at most the bound (substep_limit's, or maximum_representable_substeps). Return (Nₛ, valid, needed): Nₛ is the count as a float when valid and 1 otherwise, so it is always a safe loop operand; needed is the count needed, Inf if the ratio is not finite and positive. An invalid step is not clipped: the kernel makes its update NaN.

source
Breeze.Microphysics.step_kessler_microphysics — Method
step_kessler_microphysics(
    rᵛ,
    rᶜˡ,
    rʳ,
    Δr𝕎,
    T,
    ρ,
    ρᵗʰ,
    p,
    Δt,
    microphysics,
    constants,
    f₅,
    δT,
    FT
) -> NTuple{4, Any}

Apply one Kessler microphysics step: autoconversion, accretion, saturation adjustment, rain evaporation, and condensation.

Δr𝕎 is the sedimentation flux divergence (zero for parcel models).

ρ is the total density, which weights the rain in the evaporation rate (KW eq. 2.14); ρᵗʰ is the thermodynamic state density, at which the saturation specific humidity is evaluated. They coincide on the compressible core and in parcel models; on the anelastic core ρ is the reference density $ρᵣ$ and ρᵗʰ = pᵣ / (Rᵐ T).

Returns (rᵛ, rᶜˡ, rʳ, Δrˡ).

source
Breeze.Microphysics.thermodynamic_adjustment_factor — Method
thermodynamic_adjustment_factor(qᵛ⁺, T, 𝒰, constants)

Compute the thermodynamic adjustment factor Γ = 1 + dqᵛ⁺/dqᶜ used in relaxation-to-saturation condensation/evaporation tendencies, so that condensation alone relaxes the supersaturation excess qᵛ - qᵛ⁺ over the relaxation timescale.

The response dqᵛ⁺/dqᶜ to forming condensate from vapor follows the conserved variables of 𝒰 at fixed total water: enthalpy at fixed pressure for reference-pressure states, where qᵛ⁺ also falls with the mixture gas constant, and θ at fixed density for LiquidIceDensityState, using its chosen Exner exponent and the temperature its temperature_solver returns.

source

Microphysics.PredictedParticleProperties

Breeze.Microphysics.PredictedParticleProperties.KhairoutdinovKogan2000 — Type
struct KhairoutdinovKogan2000 <: Breeze.Microphysics.PredictedParticleProperties.AbstractWarmRainScheme

Khairoutdinov and Kogan (2000) warm-rain parameterization. Cloud self-collection is zero in this scheme.

Subgrid fraction factors

Breeze applies all warm-rain rates to the grid-mean state. A subgrid formulation would instead scale them by in-cloud and in-precipitation fractions; without those prognostics the factors are dropped, which is equivalent to SCF = SPF = 1 and SPF_clr = 0.

source
Breeze.AtmosphereModels.MicrophysicalProcessRate — Method
MicrophysicalProcessRate(
    model,
    p3::PredictedParticlePropertiesMicrophysics,
    ::Val{name}
) where name -> KernelFunctionOperation{<:Any, <:Any, <:Any, <:Any, T, K, D} where {T, K<:Breeze.Microphysics.PredictedParticleProperties.P3ProcessRateKernelFunction, D<:Tuple}

Return a KernelFunctionOperation for the P3 process rate name, which may be any field of P3ProcessRates. The most commonly visualized are

nameprocessunitssign
:condensationnet vapor ↔ cloud liquid (condensation − evaporation)kg kg⁻¹ s⁻¹+ condensation
:autoconversioncloud liquid → rain by collision–coalescencekg kg⁻¹ s⁻¹≥ 0
:accretioncloud liquid → rain, collected by rainkg kg⁻¹ s⁻¹≥ 0
:rain_evaporationrain → vaporkg kg⁻¹ s⁻¹≥ 0
:rain_condensationvapor → rainkg kg⁻¹ s⁻¹≥ 0
:depositionnet vapor ↔ ice (deposition − sublimation)kg kg⁻¹ s⁻¹+ deposition
:cloud_riming, :rain_rimingliquid → ice by rimingkg kg⁻¹ s⁻¹≥ 0

Number rates (for example :rain_self_collection) are in kg⁻¹ s⁻¹.

The rates are the instantaneous, sink-limited rates that P3 evaluates from the current model state to form its tendencies: P3 has no operator-split or substepped update, so these are exactly the rates the time stepper integrates at the start of the next stage. As in the tendency evaluation, the diffusional-growth driver uses the adiabatic temperature and pressure tendency of the local vertical velocity, and the surface temperature that gates rime splintering is the one stored by the most recent tendency evaluation.

source
Breeze.AtmosphereModels.materialize_microphysical_fields — Method
materialize_microphysical_fields(
    p3::PredictedParticlePropertiesMicrophysics,
    grid,
    bcs
) -> NamedTuple

Create prognostic and diagnostic fields for P3 microphysics.

The P3 scheme requires the following fields on grid:

Prognostic (density-weighted):

  • ρqᶜˡ: Cloud liquid mass density
  • ρqʳ, ρnʳ: Rain mass and number densities
  • ρqⁱ, ρnⁱ: Ice mass and number densities
  • ρqᶠ, ρbᶠ: Rime mass and volume densities
  • ρqʷⁱ: Liquid water on ice mass density
  • ρnᶜˡ: Cloud number density, allocated only when p3.aerosol isa AerosolActivation.
  • ρnᵃ: Unactivated aerosol number density, allocated with AerosolActivation(...; prognostic=true).
  • ρδqᵛ⁺ˡ: Vapor excess over liquid, allocated with vapor_excess = PrognosticVaporExcess().

Specific diagnostics (rewritten by update_microphysical_auxiliaries!):

  • qᵛ: Vapor specific humidity (mirrors the prognostic vapor field)
  • qᶜˡ, qʳ, nʳ, qⁱ, nⁱ, qᶠ, bᶠ, qʷⁱ: specific counterparts of the density-weighted prognostics
  • nᶜˡ, nᵃ, δqᵛ⁺ˡ: specific counterparts of the optional prognostics, each allocated alongside its own prognostic

Surface temperature (surface_temperature): one value per column for Hallett–Mossop splintering, refreshed by compute_p3_surface_temperature! before each stage's microphysical tendencies.

Sedimentation velocities (wᶜˡ, wⁿᶜˡ, wʳ, wⁿʳ, wⁱ, wⁿⁱ): z-Face fields, because the scalar flux divergence consumes them as advecting velocities at (Center, Center, Face). The surface face carries the precipitation flux out of the domain unless precipitation_boundary_condition = ImpenetrableBoundaryCondition(); the top face is held at zero so nothing sediments in from above the model top.

source
Breeze.AtmosphereModels.microphysical_tendency — Method
microphysical_tendency(
    p3::PredictedParticlePropertiesMicrophysics,
    name::Val{:ρnᶜˡ},
    ρ,
    ℳ::Breeze.Microphysics.PredictedParticleProperties.P3MicrophysicalState,
    𝒰,
    constants
)

Cloud number tendency: gains from activation and loses proportionally with cloud sinks.

In the prescribed-Nᶜˡ path (p3.aerosol === nothing), the droplet number is a scheme-level parameter, not a prognostic. ρnᶜˡ is neither allocated nor transported there, and every rate takes the prescribed value from effective_cloud_droplet_number, so this tendency is zero and is never reached through the prognostic loop.

source
Breeze.AtmosphereModels.moisture_fractions — Method
moisture_fractions(
    ::PredictedParticlePropertiesMicrophysics,
    ℳ::Breeze.Microphysics.PredictedParticleProperties.P3MicrophysicalState,
    qᵛ
) -> Breeze.Thermodynamics.MoistureMassFractions

Compute moisture mass fractions from P3 microphysical state.

After the moisture refactor, the first argument qᵛ is the prognostic vapor specific humidity (not total moisture). Returns MoistureMassFractions with vapor, liquid (cloud + rain + liquid on ice), and ice components.

source
Breeze.AtmosphereModels.precipitation_rate — Method
precipitation_rate(
    model,
    p3::PredictedParticlePropertiesMicrophysics,
    ::Val{:liquid}
) -> Field{LX, LY, LZ, O, G, I, D, T, B, Oceananigans.Fields.FieldStatus{Float64}} where {LX, LY, LZ, O, G, I, D, T, B}

Return a Field of the P3 liquid precipitation production rate, autoconversion plus accretion (kg kg⁻¹ s⁻¹), consistently with the one- and two-moment schemes. This is the rate at which cloud liquid becomes rain, not a flux; see precipitation_flux for the rate at which precipitation falls through a level.

source
Breeze.Microphysics.PredictedParticleProperties.bounded_cloud_number — Method
bounded_cloud_number(
    Nᶜˡ,
    μᶜˡ,
    qᶜˡ,
    ρ,
    ρᴸ,
    mass_scale_floor,
    parameters
)

Return the cloud number concentration [1/m³] adjusted for the cloud slope bounds.

When the cloud mass is too small (or too large) to support the prescribed Nᶜˡ at the given μᶜˡ, the slope parameter hits its bounds. The number is then recomputed from the clamped slope to maintain mass-PSD consistency, so that downstream rates (autoconversion, immersion freezing) see a physically consistent cloud number.

source
Breeze.Microphysics.PredictedParticleProperties.cloud_collection_mass_rate — Function
cloud_collection_mass_rate(
    p3,
    qᶜˡ,
    qⁱ,
    nⁱ,
    Fᶠ,
    ρᶠ,
    ρ,
    temperature_active,
    qʷⁱ=zero(typeof(qⁱ)),
    lookups=p3_ice_lookups(p3, qⁱ, qʷⁱ, nⁱ, Fᶠ, ρᶠ, ρ)
)

Ice sweep-out of cloud water, gated by temperature_active. Below freezing the collected water rimes onto the ice; above freezing it is shed as rain. Both use the same kernel, so they differ only in the gate and in what the caller does with the result — see cloud_riming_rate and cloud_warm_collection_rate.

source
Breeze.Microphysics.PredictedParticleProperties.cloud_number_per_cloud_mass — Method
cloud_number_per_cloud_mass(
    Nᶜˡ,
    ρ,
    qᶜˡ,
    minimum_mass_mixing_ratio
)

Cloud droplets per unit cloud mass, $Nᶜˡ / (ρ qᶜˡ)$ [1/kg], which converts a cloud mass rate into its number rate. Zero below minimum_mass_mixing_ratio, where the quotient would overflow to Inf and turn a zero companion rate into NaN.

source
Breeze.Microphysics.PredictedParticleProperties.cloud_number_tendency_before_homogeneous_freezing — Method
cloud_number_tendency_before_homogeneous_freezing(
    p3,
    ρ,
    qᶜˡ,
    Nᶜˡ,
    ccn_activation_mass,
    ccn_activation_number,
    autoconversion,
    accretion,
    self_collection,
    riming_number,
    freezing_number,
    warm_collection_number
)

Cloud-droplet number budget, $∂n^{cl}/∂t$ [1/kg/s], before homogeneous freezing: CCN activation is the only source, and the sinks are autoconversion, accretion, self-collection, riming, heterogeneous freezing, and above-freezing collection by ice. Each number sink is the companion of a mass rate, so the two stay consistent in mean droplet mass.

source
Breeze.Microphysics.PredictedParticleProperties.cloud_riming_number_rate — Method
cloud_riming_number_rate(p3, qᶜˡ, Nᶜˡ, ρ, riming_rate)

Compute cloud droplet number sink from riming.

Returns (Nᶜˡ / (ρ * qᶜˡ)) * riming_rate [1/kg/s]: the per-mass cloud number removal proportional to the rimed cloud mass fraction.

Arguments

  • p3: the scheme, for minimum_mass_mixing_ratio (cloud below it is absent)
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • Nᶜˡ: Cloud droplet number concentration [1/m³]
  • ρ: Air density [kg/m³]
  • riming_rate: Cloud riming mass rate [kg/kg/s]

Returns

  • Rate of cloud number loss [1/kg/s] (positive magnitude; sign applied in tendency assembly)
source
Breeze.Microphysics.PredictedParticleProperties.cloud_riming_rate — Function
cloud_riming_rate(
    p3,
    qᶜˡ,
    qⁱ,
    nⁱ,
    T,
    Fᶠ,
    ρᶠ,
    ρ,
    qʷⁱ=zero(typeof(qⁱ))
)

Compute cloud droplet collection (riming) by ice particles using the continuous collection equation with the collision kernel integrated over the ice particle size distribution.

The collection rate is:

\[\frac{dq^{cl}}{dt} = -E^{ci} q^{cl} ρ\, ρ_\text{corr}\, n^i ⟨A \mathbb{W}⟩\]

where $⟨A \mathbb{W}⟩$ is the number-normalized sweep-out kernel $\int \mathbb{W}(D) A(D) N'(D) \, dD / \int N'(D) \, dD$ [m³/s] read from Table 1 at the ice bracket, and $ρ_\text{corr}$ is the ice air-density correction.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • T: Temperature [K]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Air density [kg/m³]

Returns

  • Rate of cloud → ice conversion [kg/kg/s] (also equals rime mass gain rate)
source
Breeze.Microphysics.PredictedParticleProperties.cloud_slope_bounds — Method
cloud_slope_bounds(μᶜˡ, parameters) -> Tuple{Any, Any}

Bounds (minimum_slope, maximum_slope) [1/m] on the cloud PSD slope, λ_min = (μᶜˡ + 1) / ⟨D⟩_max and λ_max = (μᶜˡ + 1) / ⟨D⟩_min, from the mean-diameter bounds parameters.maximum_mean_droplet_diameter and parameters.minimum_mean_droplet_diameter.

Both bounds carry the same (μᶜˡ + 1) factor, so what they really bound is the mean droplet diameter rather than the slope itself. For the gamma PSD $N(D) = N_0 D^{μ} e^{-λ D}$, the number-weighted mean diameter is

\[\langle D \rangle = \frac{\int_0^∞ D\, N(D)\, dD}{\int_0^∞ N(D)\, dD} = \frac{Γ(μ + 2)}{λ\, Γ(μ + 1)} = \frac{μ + 1}{λ},\]

using $Γ(z + 1) = z\, Γ(z)$, so dividing the shared $μ + 1$ factor back out recovers the bounding diameters exactly, whatever $μᶜˡ$ was diagnosed. The defaults admit mean droplet diameters of 1–40 μm.

source
Breeze.Microphysics.PredictedParticleProperties.cloud_warm_collection_rate — Function
cloud_warm_collection_rate(
    p3,
    qᶜˡ,
    qⁱ,
    nⁱ,
    T,
    Fᶠ,
    ρᶠ,
    ρ,
    qʷⁱ=zero(typeof(qⁱ))
) -> Tuple{Any, Any}

Compute above-freezing cloud collection by melting ice.

When T > T₀, ice particles still sweep up cloud droplets via the same collection kernel as riming, but the collected water is immediately shed as rain drops (not frozen). The number of new rain drops follows process_rates.shed_drop_mass, whose default is the mass of a 1 mm drop, $π/6 ρ^L D³ ≈ 5.24 × 10⁻⁷$ kg.

Returns

  • (mass_rate, number_rate): Cloud → rain mass rate [kg/kg/s] and rain number source [1/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.compute_cloud_droplet_activation — Method
compute_cloud_droplet_activation(
    ::Nothing,
    p3,
    qᶜˡ,
    nᶜˡ,
    nᵃ,
    qᵛ,
    qᵛ⁺ˡ,
    T,
    ρ,
    constants
) -> NamedTuple{(:mass, :number), <:Tuple{Any, Any}}

Return cloud droplet activation rates (; mass, number) in [kg/kg/s] and [kg⁻¹ s⁻¹].

With nothing, droplet number is prescribed and number is zero. With AerosolActivation, both rates follow the aerosol distribution; prognostic=true also limits activation to the remaining reservoir.

source
Breeze.Microphysics.PredictedParticleProperties.compute_p3_process_rates — Method
compute_p3_process_rates(
    p3,
    ρ,
    ℳ,
    𝒰,
    constants
) -> Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates

Compute all P3 process rates (Phase 1 and Phase 2) from a microphysical state.

This is the gridless version that accepts a P3MicrophysicalState directly, suitable for use in GPU kernels where grid indexing is handled externally.

Arguments

  • p3: P3 microphysics scheme
  • ρ: Air density [kg/m³]
  • ℳ: P3MicrophysicalState containing all mixing ratios
  • 𝒰: Thermodynamic state
  • constants: Thermodynamic constants

Returns

  • P3ProcessRates containing all computed rates
source
Breeze.Microphysics.PredictedParticleProperties.consistent_rime_state — Method
consistent_rime_state(
    p3,
    qⁱ,
    qᶠ,
    bᶠ
) -> NamedTuple{(:qᶠ, :bᶠ, :Fᶠ, :ρᶠ), <:NTuple{4, Any}}

Apply a bulk rime-density consistency pass to the prognostic rime state. Returns corrected qᶠ, bᶠ, rime fraction Fᶠ, and rime density ρᶠ.

The rime-volume threshold is minimum_mass_mixing_ratio / maximum_rime_density, so that it scales with the scheme's mass floor rather than being a fixed literal.

qⁱ is the dry ice mass, so it is already the bound on rime; there is no qʷⁱ argument, unlike the reference implementation, which passes total ice and subtracts it here.

source
Breeze.Microphysics.PredictedParticleProperties.coupled_saturation_adjustment_rates — Function
coupled_saturation_adjustment_rates(
    p3,
    qᶜˡ,
    qʳ,
    nʳ,
    qⁱ,
    qʷⁱ,
    nⁱ,
    qᵛ,
    qᵛ⁺ˡ,
    qᵛ⁺ⁱ,
    Fᶠ,
    ρᶠ,
    T,
    P,
    ρ,
    constants,
    transport,
    q,
    μᶜˡ,
    λᶜˡ,
    nᶜˡ_bounded,
    temperature_tendency,
    pressure_tendency,
    lookups=p3_ice_lookups(p3, qⁱ, qʷⁱ, nⁱ, Fᶠ, ρᶠ, ρ)
) -> Breeze.Microphysics.PredictedParticleProperties.P3CoupledVaporRates

Compute cloud, rain, and ice diffusional growth rates using a shared semi-analytic saturation adjustment, in the SCF = SPF = 1 limit; the subgrid cloud/precipitation fraction framework is handled separately.

source
Breeze.Microphysics.PredictedParticleProperties.deposition_nucleation_rate — Method
deposition_nucleation_rate(
    p3,
    T,
    qᵛ,
    qᵛ⁺ⁱ,
    nⁱ,
    ρ
) -> Tuple{Any, Any}

Compute ice nucleation rate from deposition/condensation freezing.

New ice crystals nucleate when temperature is below a threshold and the air is supersaturated with respect to ice. Uses Cooper (1986). The process is gated on cloud-side ice supersaturation. Breeze carries no subgrid cloud fraction, which is the SCF = 1 limit: the grid cell is treated as uniformly cloudy, so the vapor passed in is both the grid-mean and the cloud-side value. If a subgrid cloud-fraction path is added, pass the cloud-side vapor state here rather than a grid-mean vapor state.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • T: Temperature [K]
  • qᵛ: Cloud-side vapor mass fraction [kg/kg] (grid-mean when SCF = 1)
  • qᵛ⁺ⁱ: Saturation vapor mass fraction over ice [kg/kg]
  • nⁱ: Current ice number concentration [1/kg]
  • ρ: Air density [kg/m³]

Returns

  • Tuple (nucleated_mass_rate, nucleated_number_rate): mass rate [kg/kg/s] and number rate [1/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.deposition_ventilation — Method
deposition_ventilation(
    vent::Breeze.Microphysics.PredictedParticleProperties.P3Table4D,
    vent_e::Breeze.Microphysics.PredictedParticleProperties.P3Table4D,
    m_mean,
    Fᶠ,
    Fˡ,
    ρᶠ,
    parameters,
    ν,
    Dᵛ,
    ρ_correction
)

Compute per-particle ventilation integral C(D) × f_v(D) for deposition using PSD-integrated lookup tables.

source
Breeze.Microphysics.PredictedParticleProperties.diagnose_cloud_dsd — Method
diagnose_cloud_dsd(
    p3,
    qᶜˡ,
    nᶜˡ,
    ρ
) -> NamedTuple{(:Nᶜˡ, :nᶜˡ, :μᶜˡ, :λᶜˡ), <:NTuple{4, Any}}

Diagnose the cloud PSD state from cloud liquid and cloud number.

The cloud number is converted from the specific number nᶜˡ [kg⁻¹] (prognostic, or the prescribed concentration divided by ρ) to an absolute concentration, then diagnose μᶜˡ via Liu-Daum, apply the slope bounds, and return the adjusted cloud number together with the shape and slope parameters μᶜˡ and λᶜˡ.

source
Breeze.Microphysics.PredictedParticleProperties.effective_cloud_droplet_number — Method
effective_cloud_droplet_number(
    p3::PredictedParticlePropertiesMicrophysics,
    ρnᶜˡ,
    ρ
)

Effective cloud droplet number concentration [kg⁻¹] seen by P3's process rates.

In the prescribed-Nᶜˡ path (p3.aerosol === nothing), the droplet number is always p3.cloud.number_concentration at every microphysics call, so this helper returns that prescribed value divided by ρ and ignores its ρnᶜˡ argument. Droplet number is not a state variable in that configuration: prognostic_field_names omits ρnᶜˡ and materialize_microphysical_fields does not allocate it.

In the prognostic path (aerosol activation enabled), it returns the advected per-mass number μ.ρnᶜˡ / ρ as usual.

source
Breeze.Microphysics.PredictedParticleProperties.external_vapor_excess_forcing — Method
external_vapor_excess_forcing(
    qᵛ⁺,
    ℒ,
    T,
    P,
    temperature_tendency,
    pressure_tendency,
    constants
)

Externally driven change in the vapor excess over a surface with saturation specific humidity qᵛ⁺ and latent heat ℒ, at fixed vapor,

\[-∂ₜqᵛ⁺ = -(dqᵛ⁺ / dT) ∂ₜT + qᵛ⁺ ∂ₜp / p ,\]

since $qᵛ⁺ ∝ 1/p$ at fixed temperature and composition. In adiabatic ascent the pressure term offsets about a fifth of the cooling term. Over liquid, this forcing drives diffusional growth and, with PrognosticVaporExcess, the prognostic $δqᵛ⁺ˡ$; over both surfaces it adds to the vapor excess available to the saturation-adjustment caps in limit_vapor_rates. Resolved vapor transport, turbulent mixing, radiation, and user forcing are omitted.

source
Breeze.Microphysics.PredictedParticleProperties.freezing_capacities — Method
freezing_capacities(
    p3,
    nⁱ,
    T,
    qᵛ,
    ρ,
    ρᵗʰ,
    constants,
    transport,
    lookups
) -> Tuple{Any, Any}

Compute the wet growth and refreezing capacities, the maximum rates at which collected water and the liquid coating can freeze, from the ventilated heat balance of an ice particle whose surface is held at T₀. Both share the conduction and vapor-diffusion terms; see wet_growth_capacity and refreezing_rate for what each freezes. The total density ρ weights the vapor flux; the freezing-point saturation fraction is evaluated at the thermodynamic state density ρᵗʰ.

Returns

  • (wet_growth, refreezing) capacities [kg/kg/s], zero when T ≥ T₀
source
Breeze.Microphysics.PredictedParticleProperties.homogeneous_freezing_cloud_rate — Method
homogeneous_freezing_cloud_rate(
    p3,
    qᶜˡ,
    Nᶜˡ,
    T,
    ρ
) -> Tuple{Any, Any}

Compute homogeneous freezing rate of cloud droplets.

Below −40°C (233.15 K) all supercooled cloud liquid freezes instantaneously. The frozen mass deposits as dense rime at $ρ_{\text{rim}} = 900$ kg/m³ (solid ice sphere), following Morrison and Milbrandt (2015).

All cloud droplets are transferred to ice; the number rate is $N_{\text{hom}} = N^{cl} / (ρ τ_{\text{hom}})$.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • Nᶜˡ: Cloud droplet number concentration [1/m³]
  • T: Temperature [K]
  • ρ: Air density [kg/m³]

Returns

  • Tuple (frozen_mass_rate, frozen_number_rate) containing the cloud-to-ice mass rate [kg/kg/s] and number rate [1/kg/s]

Example

using Breeze.Microphysics.PredictedParticleProperties:    homogeneous_freezing_cloud_ratep3 = PredictedParticlePropertiesMicrophysics()Q, N = homogeneous_freezing_cloud_rate(p3, 1e-3, 100e6, 230.0, 1.2)round.((Q, N), sigdigits=4)# output(0.0001, 8.333e6)
source
Breeze.Microphysics.PredictedParticleProperties.homogeneous_freezing_rain_rate — Method
homogeneous_freezing_rain_rate(
    p3,
    qʳ,
    nʳ,
    T
) -> Tuple{Any, Any}

Compute homogeneous freezing rate of rain drops.

Below −40°C (233.15 K) all supercooled rain freezes instantaneously. The frozen mass deposits as dense rime at $ρ_{\text{rim}} = 900$ kg/m³, following Morrison and Milbrandt (2015).

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qʳ: Rain mass fraction [kg/kg]
  • nʳ: Rain number concentration [1/kg]
  • T: Temperature [K]

Returns

  • Tuple (frozen_mass_rate, frozen_number_rate) containing the rain-to-ice mass rate [kg/kg/s] and number rate [1/kg/s]

Example

using Breeze.Microphysics.PredictedParticleProperties:    homogeneous_freezing_rain_ratep3 = PredictedParticlePropertiesMicrophysics()Q, N = homogeneous_freezing_rain_rate(p3, 1e-3, 1e4, 220.0)round.((Q, N), sigdigits=4)# output(0.0001, 1000.0)
source
Breeze.Microphysics.PredictedParticleProperties.homogeneous_freezing_rate — Method
homogeneous_freezing_rate(p3, q, n, T) -> Tuple{Any, Any}

Instantaneous homogeneous freezing, shared by the cloud and rain paths: below the homogeneous freezing threshold the whole population is transferred to ice over homogeneous_freezing_timescale, with no mass-number consistency cap. n is a number per unit mass [1/kg].

source
Breeze.Microphysics.PredictedParticleProperties.ice_aggregation_rate — Function
ice_aggregation_rate(
    p3,
    qⁱ,
    nⁱ,
    T,
    Fᶠ,
    ρᶠ,
    ρ,
    qʷⁱ=zero(typeof(qⁱ)),
    lookups=p3_ice_lookups(p3, qⁱ, qʷⁱ, nⁱ, Fᶠ, ρᶠ, ρ)
)

Compute ice self-collection (aggregation) rate using proper collision kernel.

Ice particles collide and stick together, reducing number concentration without changing total mass. The collision kernel is:

\[K(D_1, D_2) = E^{ii} × \frac{π}{4}(D_1 + D_2)^2 × |\mathbb{W}_1 - \mathbb{W}_2|\]

The number tendency is:

\[\frac{dn^i}{dt} = -\frac{ρ}{2} ∫∫ K(D_1, D_2) N'(D_1) N'(D_2) dD_1 dD_2\]

The ρ factor converts the volumetric collision kernel [m³/s] to the mass-specific number tendency [1/kg/s] when nⁱ is in [1/kg].

The sticking efficiency $E^{ii}$ increases with temperature (more sticky near 0°C). See Morrison and Milbrandt (2015a).

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • T: Temperature [K]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Air density [kg/m³]

Returns

  • Rate of ice number loss [1/kg/s] (positive magnitude; sign applied in tendency assembly)
source
Breeze.Microphysics.PredictedParticleProperties.ice_melting_number_rate — Method
ice_melting_number_rate(qⁱ, nⁱ, qⁱ_melt_rate)

Compute ice number loss from melting.

Number of melted particles equals number of rain drops produced.

Arguments

  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • qⁱ_melt_rate: Ice mass melting rate [kg/kg/s]

Returns

  • Rate of ice number loss [1/kg/s] (positive magnitude; sign applied in tendency assembly)
source
Breeze.Microphysics.PredictedParticleProperties.ice_melting_rate — Method
ice_melting_rate(
    p3,
    qⁱ,
    nⁱ,
    qʷⁱ,
    T,
    qᵛ,
    Fᶠ,
    ρᶠ,
    ρ,
    ρᵗʰ,
    constants,
    transport
)

Compute ice melting rate using the heat balance equation from Morrison & Milbrandt (2015a) Eq. 44.

The melting rate is determined by the heat flux to the particle:

\[\frac{dm}{dt} = -\frac{2π \, \text{capm}}{ℒᶠʳ} × [Kᵃ(T-T_0) + ρ ℒˡ Dᵛ(q^v - q^{v+}_0)] × f^{ve}\]

where capm = cap × D is the P3 capacitance convention (2× physical C).

where:

  • C is the capacitance
  • ℒᶠʳ is the latent heat of fusion
  • Kᵃ is thermal conductivity of air
  • T_0 is the freezing temperature
  • ℒˡ is latent heat of vaporization
  • Dᵛ is diffusivity of water vapor
  • qᵛ, qᵛ⁺(T₀) are the vapor and saturation specific humidities (total-air mass fractions) at T₀; qᵛ⁺(T₀) = ρᵛ⁺(T₀)/ρᵗʰ so that ρᵗʰ (qᵛ - qᵛ⁺(T₀)) = ρᵛ - ρᵛ⁺(T₀)
  • fᵛᵉ is the ventilation factor

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • T: Temperature [K]
  • qᵛ: Vapor mass fraction [kg/kg]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Total density, weighting the vapor-diffusion heat flux and the ice lookups [kg/m³]
  • ρᵗʰ: Thermodynamic state density, at which the freezing-point saturation fraction is evaluated [kg/m³]
  • constants: Thermodynamic constants
  • transport: Pre-computed air transport properties (; Dᵛ, Kᵃ, ν)

Returns

  • Rate of ice → rain conversion [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.ice_melting_rates — Method
ice_melting_rates(
    p3,
    qⁱ,
    nⁱ,
    qʷⁱ,
    T,
    qᵛ,
    Fᶠ,
    ρᶠ,
    ρ,
    ρᵗʰ,
    constants,
    transport
) -> NamedTuple{(:partial_melting, :complete_melting), <:Tuple{Any, Any}}

Compute partitioned ice melting rates using PSD-resolved partitioning.

Above freezing, ice particles melt. The meltwater is partitioned using tabulated small/large ice ventilation integrals:

  • Complete melting (small particles, D ≤ D_crit): Meltwater sheds to rain
  • Partial melting (large particles, D > D_crit): Meltwater stays as liquid coating (qʷⁱ)

Requires tabulated small/large ice ventilation integrals.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • qʷⁱ: Liquid water on ice [kg/kg]
  • T: Temperature [K]
  • qᵛ: Vapor mass fraction [kg/kg]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Total density, weighting the vapor-diffusion heat flux and the ice lookups [kg/m³]
  • ρᵗʰ: Thermodynamic state density, at which the freezing-point saturation fraction is evaluated [kg/m³]
  • constants: Thermodynamic constants
  • transport: Pre-computed air transport properties (; Dᵛ, Kᵃ, ν)

Returns

  • NamedTuple with partial_melting and complete_melting rates [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.ice_terminal_velocities — Method
ice_terminal_velocities(
    p3,
    qⁱ,
    nⁱ,
    Fᶠ,
    ρᶠ,
    ρ;
    Fˡ=zero(typeof(qⁱ))
) -> Breeze.Microphysics.PredictedParticleProperties.IceTerminalVelocities

Compute both ice terminal velocities (mass- and number-weighted) in a single call, sharing the mean particle mass, the air density correction, and the 4D interpolation indices between the two table reads.

ice_terminal_velocity_mass_weighted remains available for the one caller that needs the mass-weighted speed alone.

See Heymsfield et al. (2007) for the density correction exponent and Morrison and Milbrandt (2015a) for the P3 fall speed framework.

Arguments

  • p3: P3 microphysics scheme (provides parameters and lookup tables)
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • Fᶠ: Rime mass fraction (qᶠ/qⁱ)
  • ρᶠ: Rime density [kg/m³]
  • ρ: Air density [kg/m³]
  • Fˡ: Liquid fraction (optional, for tabulated lookup)

Returns

  • IceTerminalVelocities with fields mass_weighted, number_weighted [m/s] (both positive downward)
source
Breeze.Microphysics.PredictedParticleProperties.ice_terminal_velocity_mass_weighted — Method
ice_terminal_velocity_mass_weighted(
    p3,
    qⁱ,
    nⁱ,
    Fᶠ,
    ρᶠ,
    ρ;
    Fˡ=zero(typeof(qⁱ))
)

Compute mass-weighted terminal velocity for ice.

Uses pre-computed lookup tables for accurate size-distribution integration. See Mitchell (1996) and Morrison and Milbrandt (2015a).

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • Fᶠ: Rime mass fraction (qᶠ/qⁱ)
  • ρᶠ: Rime density [kg/m³]
  • ρ: Air density [kg/m³]
  • Fˡ: Liquid fraction (optional, for tabulated lookup)

Returns

  • Mass-weighted fall speed [m/s] (positive downward)
source
Breeze.Microphysics.PredictedParticleProperties.immersion_freezing_cloud_rate — Method
immersion_freezing_cloud_rate(
    p3,
    qᶜˡ,
    Nᶜˡ,
    T,
    ρ
) -> Tuple{Any, Any}

Compute immersion freezing rate of cloud droplets using the Barklie and Gokhale (1959) stochastic volume-dependent freezing parameterization.

The probability per droplet per second of freezing is $J₀ V_{\text{drop}} \exp(a ΔT)$, where $J₀ ≈ 2$ m⁻³s⁻¹ is the nucleation rate coefficient ($a = 0.65$) and $V_{\text{drop}}$ is the individual droplet volume. For monodisperse cloud droplets this gives a mass freezing rate proportional to $(q^{cl})^2 / N^{cl}$, making freezing negligible for small droplets.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • Nᶜˡ: Cloud droplet number concentration [1/m³]
  • T: Temperature [K]
  • ρ: Air density [kg/m³]

Returns

  • Tuple (frozen_mass_rate, frozen_number_rate): mass rate [kg/kg/s] and number rate [1/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.immersion_freezing_rain_rate — Method
immersion_freezing_rain_rate(
    p3,
    qʳ,
    nʳ,
    T,
    μʳ
) -> Tuple{Any, Any}

Compute immersion freezing rate of rain drops.

Rain drops freeze when temperature is below a threshold. Uses Barklie and Gokhale (1959) stochastic freezing parameterization.

The PSD correction $C(\mu_r) = \Gamma(\mu_r+7)\Gamma(\mu_r+1)/\Gamma(\mu_r+4)^2$ is computed from the actual rain shape parameter $\mu_r$, not from a fixed value.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qʳ: Rain mass fraction [kg/kg]
  • nʳ: Rain number concentration [1/kg]
  • T: Temperature [K]
  • μʳ: Rain PSD shape parameter [-] (0 for exponential)

Returns

  • Tuple (frozen_mass_rate, frozen_number_rate): mass rate [kg/kg/s] and number rate [1/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.limit_vapor_rates — Method
limit_vapor_rates(
    cond,
    ccn_activation_mass,
    ccn_activation_number,
    rain_cond,
    rain_evap,
    dep,
    coat_cond,
    coat_evap,
    nuc_q,
    nuc_n,
    qᵛ,
    qᵛ⁺ˡ,
    T,
    P,
    qᵗ,
    constants,
    dt_safety,
    freezing_temperature
) -> NamedTuple{(:cond, :ccn_activation_mass, :ccn_activation_number, :rain_cond, :rain_evap, :dep, :coat_cond, :coat_evap, :nuc_q, :nuc_n), <:NTuple{10, Any}}

Cap vapor sinks and sources against the moist-adiabatic saturation-adjustment budget.

Defining the liquid saturation-adjustment increment δqˡ = (qᵛ - qᵛ⁺ˡ + Aˡ τ) / ξˡ with the moist-static feedback factor ξˡ = 1 + ℒˡ² qᵛ⁺ˡ / (cᵖᵈ Rᵛ T²), where Aˡ = -∂ₜqᵛ⁺ˡ is the external forcing (see external_vapor_excess_forcing) and τ = dt_safety:

  • Liquid-phase condensation sinks (cond > 0, ccn_activation_mass, rain_cond, coat_cond) cannot exceed max(0, δqˡ).
  • Liquid-phase evaporation sources (cond < 0, rain_evap, coat_evap) cannot exceed max(0, -δqˡ).

The rescaled liquid tendencies are then carried into a post-liquid state (qᵛ_after, T_after), and qᵛ⁺ⁱ_after is recomputed at T_after to evaluate ξⁱ_after = 1 + ℒⁱ_after² qᵛ⁺ⁱ_after / (cᵖᵈ Rᵛ T_after²). With the ice increment δqⁱ = (qᵛ_after - qᵛ⁺ⁱ_after) / ξⁱ_after:

  • Ice-phase deposition sinks (dep > 0, nuc_q) cannot exceed max(0, δqⁱ).
  • Ice-phase sublimation sources (dep < 0) cannot exceed max(0, -δqⁱ).

Number rates ccn_activation_number and nuc_n are scaled by the same factor as their companion mass rates to preserve mean particle mass.

The external forcing counts as available because the growth rates include it: they are evaluated from the current state, which does not yet carry the cooling and expansion over the next dt_safety. Without it the caps bind in steady ascent and hold the vapor excess near A τ rather than where diffusional growth balances the forcing. The ice-phase increment δqⁱ likewise includes Aⁱ τ.

Returns a NamedTuple of the possibly-rescaled rates.

source
Breeze.Microphysics.PredictedParticleProperties.parse_lookup_table_file — Method
parse_lookup_table_file(filepath::AbstractString, FT::Type)

Parse the P3 ice ASCII table file, which carries both table blocks.

Returns two dictionaries:

  • table1_fields: Dict of Symbol => Array{FT,4} for ice integrals, with axes (normalized mass, Fᶠ, Fˡ, rime-density index)
  • table2_fields: Dict of Symbol => Array{FT,5} for rain-ice collection, with axes (normalized mass, λʳ reversed into ascending order, Fᶠ, Fˡ, rime-density index)
source
Breeze.Microphysics.PredictedParticleProperties.prescribed_cloud_activation_rate — Method
prescribed_cloud_activation_rate(
    p3,
    qᶜˡ,
    qᵛ,
    qᵛ⁺ˡ,
    T,
    ρ,
    Nᶜˡ,
    constants
)

Return the vapor-to-cloud mass rate [kg/kg/s] for prescribed droplet concentration Nᶜˡ.

In supersaturated air, supply seed mass up to $N^{cl} / ρ × m_{\text{drop}}$ where $m_{\text{drop}} = (4π/3) ρ_w r^3$ and the default seed radius is 1 μm. The supersaturation cap uses $ξˡ = 1 + ℒˡ² q^{v+ℓ} / (c_p^d R_v T²)$ with the dry-air heat capacity, consistent with limit_vapor_rates and prognostic_vapor_excess_adjustment.

source
Breeze.Microphysics.PredictedParticleProperties.prognostic_vapor_excess_adjustment — Method
prognostic_vapor_excess_adjustment(
    p3,
    qᶜˡ,
    qᵛ⁺ˡ,
    δqᵛ⁺ˡ,
    T,
    ρᵗʰ,
    𝒰,
    constants
) -> NamedTuple{(:cloud_water_adjustment, :rate, :qᶜˡ, :qᵛ, :qᵛ⁺ˡ, :T, :P, :q, :ρᵗʰ), <:NTuple{9, Any}}

Bounded Grabowski–Morrison saturation adjustment applied before the Morrison–Gettelman semi-analytic rates. It aligns qᵛ, qᶜˡ, T, qᵛ⁺ˡ, and qᵛ⁺ⁱ with each other before the per-species rate equations are evaluated.

Given the advected vapor excess over liquid $δqᵛ⁺ˡ$, the diagnostic local $qᵛ - qᵛ⁺ˡ$, and the saturation response $Γˡ = 1 + dqᵛ⁺ˡ/dqᶜˡ$ of Microphysics.thermodynamic_adjustment_factor, compute the cloud-water increment

\[ε = (qᵛ - qᵛ⁺ˡ - δqᵛ⁺ˡ) / Γˡ\]

clamped to physical limits: $ε$ cannot evaporate more cloud than is locally available ($ε ≥ -qᶜˡ$), and when the advected $δqᵛ⁺ˡ$ is negative $ε ≤ 0$ (no spurious condensation). The returned $rate = ε / τ$ is sized to sink_limiting_timescale, so one host step with $dt = sink_limiting_timescale$ reproduces the one-shot $ε$ exactly. If the host integrates with $dt ≠ τ$ the vapor-excess alignment relaxes over multiple steps rather than landing in one.

When vapor_excess = DiagnosticVaporExcess(), dispatch bypasses the adjustment and the local state passes through unchanged.

The aligned state is the host's own state at the new composition: it keeps the host's conserved thermodynamic variable (θˡⁱ or s), at fixed pressure for reference-pressure states (anelastic core, parcels) and at fixed density for LiquidIceDensityState (compressible core), as vapor_excess_after_moisture_update does. Γˡ is the response under the same constraint, so $qᵛ - qᵛ⁺ˡ$ of the aligned state matches $δqᵛ⁺ˡ$ to first order in $ε$. Its q, ρᵗʰ, and P are returned. This alignment is Breeze's, so it follows the host thermodynamics rather than the dry-air cᵖᵈ psychrometric convention of the Morrison–Gettelman rates that follow it.

source
Breeze.Microphysics.PredictedParticleProperties.rain_accretion_rate — Function
rain_accretion_rate(p3, qᶜˡ, qʳ, ρ=one(qᶜˡ))

Compute rain accretion rate, dispatched on p3.warm_rain_scheme.

Falling rain drops collect cloud droplets via gravitational sweep-out. See rain_autoconversion_rate for the scheme menu.

\[\dot q^{r}_{\mathrm{accr}} = \mathbb{C}_{\mathrm{accr},1} (q^{cl} q^r)^{\mathbb{C}_{\mathrm{accr},2}}.\]

Arguments

  • p3: P3 microphysics scheme
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • qʳ: Rain mass fraction [kg/kg]
  • ρ: Air density [kg/m³] (unused by KK2000; defaults to 1)

Returns

  • Rate of cloud → rain conversion [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.rain_autoconversion_rate — Function
rain_autoconversion_rate(p3, qᶜˡ, Nᶜˡ, ρ, qʳ=zero(qᶜˡ))

Compute rain autoconversion rate, dispatched on p3.warm_rain_scheme.

Cloud droplets larger than a threshold undergo collision-coalescence to form rain. For the KK2000 branch,

\[\dot q^{r}_{\mathrm{auto}} = \mathbb{C}_{\mathrm{auto},1} (q^{cl})^{\mathbb{C}_{\mathrm{auto},2}} \left(\frac{N^{cl}}{N^{cl}_r}\right)^{\mathbb{C}_{\mathrm{auto},3}},\]

gated to zero below $q^{cl} = \mathbb{C}_{\mathrm{auto},4}$. The reference concentration $N^{cl}_r$ fixes units and is not an independently identifiable free parameter.

Available schemes:

Arguments

  • p3: P3 microphysics scheme (provides parameters and scheme selector)
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • Nᶜˡ: Cloud droplet number concentration [1/m³]
  • ρ: Air density [kg/m³]
  • qʳ: Rain mass fraction [kg/kg] (unused by KK2000; retained for the scheme-dispatch signature)

Returns

  • Rate of cloud → rain conversion [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.rain_breakup_rate — Method
rain_breakup_rate(p3, qʳ, nʳ, self_collection)

Compute rain breakup rate.

Large rain drops spontaneously break up into smaller fragments, producing a number source that counterbalances self-collection. Uses a two-piece function of $\bar D^r = (q^r / (π ρ^L n^r))^{1/3} = 1/λ^r$. For the exponential rain DSD this is the number-mean diameter; the diameter of the mean particle mass is $6^{1/3} \bar D^r$.

  1. $\bar D^r < \mathbb{C}_{\mathrm{brkp},1}$: no breakup effect.
  2. $\bar D^r ≥ \mathbb{C}_{\mathrm{brkp},1}$: $f_{brkp} = 2 - \exp[\mathbb{C}_{\mathrm{brkp},2} (\bar D^r - \mathbb{C}_{\mathrm{brkp},1})]$.

The breakup source is $(1 - f_{brkp})$ times the self-collection sink. The net rain-number tendency changes sign only when $f_{brkp} = 0$, at $\bar D^r = \mathbb{C}_{\mathrm{brkp},1} + \log(2) / \mathbb{C}_{\mathrm{brkp},2}$.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qʳ: Rain mass fraction [kg/kg]
  • nʳ: Rain number concentration [1/kg]
  • self_collection: Self-collection rate [1/kg/s] (positive magnitude)

Returns

  • Breakup rate [1/kg/s] (positive = number source)
source
Breeze.Microphysics.PredictedParticleProperties.rain_evaporation_rate — Function
rain_evaporation_rate(
    p3,
    qʳ,
    nʳ,
    qᵛ,
    qᵛ⁺ˡ,
    T,
    ρ,
    P,
    constants,
    transport=air_transport_properties(T, P, constants)
)

Compute rain evaporation rate using ventilation-enhanced diffusion.

Rain drops evaporate when the ambient air is subsaturated (qᵛ < qᵛ⁺ˡ). The evaporation rate is enhanced by ventilation (air flow around falling drops).

p3.rain.evaporation is the tabulated velocity-diameter integral $I_{\mathbb{W}D}$ built by tabulate_rain_from_quadrature. The inner method computes λʳ from (qʳ, Nʳ), assembles the full ventilation integral I_evap from that table read plus the runtime 1/√ν, ℂᵛᵉⁿᵗ and Schmidt contributions, then applies dqʳ/dt = 2π × Nʳ₀ × I_evap × (S-1) / thermo_factor (Mason 1971, capacitance C = D/2 so 4πC = 2πD).

\[\frac{dm}{dt} = \frac{4\pi C f_v (S - 1)}{\frac{ℒˡ}{Kᵃ T}(\frac{ℒˡ}{R_v T} - 1) + \frac{R_v T}{e_s Dᵛ}},\quad C = D/2\]

Arguments

  • p3: P3 microphysics scheme (provides parameters and evaporation table)
  • qʳ: Rain mass fraction [kg/kg]
  • nʳ: Rain number concentration [1/kg]
  • qᵛ: Vapor mass fraction [kg/kg]
  • qᵛ⁺ˡ: Saturation vapor mass fraction over liquid [kg/kg]
  • T: Temperature [K]
  • ρ: Air density [kg/m³]; currently unused
  • P: Air pressure [Pa]
  • constants: Thermodynamic constants

Returns

  • Rate of rain evaporation [kg/kg/s] (positive magnitude; sign applied in tendency assembly)
source
Breeze.Microphysics.PredictedParticleProperties.rain_fall_speed — Method
rain_fall_speed(D, ρ_correction, fall_speed)

Piecewise Gunn-Kinzer / Beard rain terminal velocity [m/s] at diameter D [m], scaled by ρ_correction. Captures Stokes drag below the first transition diameter (D ≈ 134 μm by default) and the terminal-velocity plateau above the third (D ≈ 3.5 mm).

The branch velocity scales, mass exponents, boundary diameters and plateau speed come from fall_speed, a RainFallSpeed. The published fit is stated in centimetres per second per gram^exponent; the scales stored in the container are already converted to m/s, and the mass argument is the dimensionless ratio m(D) / (1 g), which is numerically the drop mass in grams.

Used by all three rain quadrature evaluators, so a configured law reaches the mass-weighted velocity, number-weighted velocity, and evaporation velocity-diameter tables alike.

source
Breeze.Microphysics.PredictedParticleProperties.rain_number_tendency_before_homogeneous_freezing — Method
rain_number_tendency_before_homogeneous_freezing(
    p3,
    autoconversion,
    melting_number,
    evaporation_number,
    self_collection,
    breakup,
    riming_number,
    freezing_number,
    shedding_number,
    cloud_warm_collection,
    warm_collection_number,
    wet_growth_shedding_number
)

Rain-drop number budget, $∂n^r/∂t$ [1/kg/s], before homogeneous freezing. Sources: autoconversion, melting ice, drop breakup, shedding, wet-growth shedding, and — outside liquid-fraction mode — cloud water swept up by melting ice and shed as drops. Sinks: evaporation, self-collection, riming, heterogeneous freezing, and above-freezing collection by ice.

source
Breeze.Microphysics.PredictedParticleProperties.rain_riming_rate — Function
rain_riming_rate(
    p3,
    qʳ,
    nʳ,
    qⁱ,
    nⁱ,
    T,
    Fᶠ,
    ρᶠ,
    ρ,
    qʷⁱ=zero(typeof(qⁱ))
)

Compute rain collection (riming) by ice particles from the Table 2 double-PSD collection kernel.

Double-PSD integration:

Table 2 integrates over both the ice PSD and the rain PSD. The collision cross section is $(√{A(D^i)} + √{π/4} D^r)^2$, where $A(D^i)$ is the ice projected area. For spherical ice this reduces to $π/4 (D^i + D^r)^2$. The ice PSD is normalized to unit number, and the rain intercept $N_0^r$ is factored out, so the rate is $\mathcal{K} × N_0^r × n^i × ρ × ρ_\text{corr} × E^{ri}$, with $N_0^r = n^r λ^r$ at $μ^r = 0$. Here $n^r$ is the mass-specific number recomputed from the bounded rain slope, so the rain PSD preserves mass when the slope limiter binds.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • qʳ: Rain mass fraction [kg/kg]
  • nʳ: Rain number concentration [1/kg]; floored at minimum_number_mixing_ratio
  • qⁱ: Ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • T: Temperature [K]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Air density [kg/m³]

Returns

  • Rate of rain → ice conversion [kg/kg/s] (also equals rime mass gain rate)
source
Breeze.Microphysics.PredictedParticleProperties.rain_seed_drop_mass — Method
rain_seed_drop_mass(p3)

Mass per newly-formed rain drop produced by autoconversion, dispatched on p3.warm_rain_scheme. Used to convert autoconversion mass rate into a rain number source.

For KK2000 this is the mass of a 25 μm radius drop ≈ 6.545e-11 kg, read from the configurable p3.process_rates.initial_rain_drop_mass. The 25 μm radius appears only inside that keyword's default expression; there is no separate radius keyword.

source
Breeze.Microphysics.PredictedParticleProperties.rain_self_collection_rate — Method
rain_self_collection_rate(p3, qʳ, nʳ, ρ)

Compute rain self-collection rate (number tendency only). Dispatches on p3.warm_rain_scheme.

Large rain drops collect smaller ones, reducing number but conserving mass. KK2000 uses $\dot n^r_{\mathrm{self}} = \mathbb{C}_{\mathrm{self},1} ρ q^r n^r$, with $\mathbb{C}_{\mathrm{self},1} = 5.78$ m³ kg⁻¹ s⁻¹ by default.

Arguments

  • p3: P3 microphysics scheme (provides parameters and scheme selector)
  • qʳ: Rain mass fraction [kg/kg]
  • nʳ: Rain number concentration [1/kg]
  • ρ: Air density [kg/m³]

Returns

  • Rate of rain number loss [1/kg/s] (positive magnitude; sign applied in tendency assembly)
source
Breeze.Microphysics.PredictedParticleProperties.rain_slope_parameter — Method
rain_slope_parameter(qʳ, nʳ, parameters)

Return the exponential rain particle size distribution slope parameter $λʳ$ diagnosed from the rain mass concentration qʳ and number concentration nʳ. The result is clamped between parameters.minimum_rain_slope and parameters.maximum_rain_slope.

source
Breeze.Microphysics.PredictedParticleProperties.rain_terminal_velocities — Method
rain_terminal_velocities(
    p3,
    qʳ,
    nʳ,
    ρ
) -> Breeze.Microphysics.PredictedParticleProperties.RainTerminalVelocities

Compute mass- and number-weighted rain terminal velocities together, sharing the slope-parameter, ρ-correction, and log10(λ_r) computations between the two table lookups.

Returns

  • RainTerminalVelocities with fields mass_weighted, number_weighted [m/s] (positive downward)
source
Breeze.Microphysics.PredictedParticleProperties.rain_velocity_moment_ratio — Method
rain_velocity_moment_ratio(
    nodes,
    weights,
    λʳ,
    diameter_weight::G,
    floors,
    fall_speed
) where G

Velocity moment ratio of an exponential rain PSD on the Chebyshev-Gauss nodes,

\[\frac{\int_0^\infty \mathbb{W}(D) \, g(D) \, e^{-λ^r D} \, dD} {\int_0^\infty g(D) \, e^{-λ^r D} \, dD}\]

where diameter_weight supplies $g(D)$: identity_weight for the number-weighted velocity, cubed_weight for the mass-weighted one (the constant spherical-water mass factor cancels between numerator and denominator).

$\mathbb{W}$ is the piecewise Gunn-Kinzer/Beard fall speed configured by fall_speed at reference density; apply (ρ₀/ρ)^0.54 at the call site. The floor on the denominator is a divide-by-zero guard on that same integral; a machine-epsilon floor would instead suppress valid Float32 velocities.

source
Breeze.Microphysics.PredictedParticleProperties.rain_ventilation_integral — Method
rain_ventilation_integral(
    table,
    ventilation,
    qʳ,
    nʳ,
    ν,
    Dᵛ,
    parameters
) -> NamedTuple{(:λʳ, :Nʳ₀, :integral), <:Tuple{Any, Any, Any}}

Rain ventilation integral and the slope quantities that go with it:

\[I_{evap}(λ^r) = \frac{\mathbb{C}_{\mathrm{vent},1}}{(λ^r)^2} + \mathbb{C}_{\mathrm{vent},2} \, \frac{Sc^{1/3}}{\sqrt{ν}} \, I_{\mathbb{W}D}(λ^r)\]

$I_{\mathbb{W}D}$ comes from the tabulated table, which stores $∫ D \sqrt{\mathbb{W} D} e^{-λ^r D} dD$ with neither ν nor the Schmidt number baked in, so both T,P-dependent factors are applied here. $\mathbb{C}_{\mathrm{vent},1}$ and $\mathbb{C}_{\mathrm{vent},2}$ come from ventilation, a RainVentilation, for the same reason: neither is baked into the table, so both remain configurable at runtime. Returns (; λʳ, Nʳ₀, integral), since every caller needs the intercept $N^r_0 = n^r λ^r$ alongside the integral.

Consumed by rain_evaporation_rate and by the coupled saturation-adjustment relaxation coefficient, both of which pass p3.rain.ventilation.

source
Breeze.Microphysics.PredictedParticleProperties.rain_warm_collection_rate — Function
rain_warm_collection_rate(
    p3,
    qʳ,
    nʳ,
    qⁱ,
    nⁱ,
    T,
    Fᶠ,
    ρᶠ,
    ρ,
    qʷⁱ=zero(typeof(qⁱ))
)

Compute above-freezing rain collection by melting ice.

When T > T₀ and liquid fraction is active, rain drops collected by ice contribute to the liquid coating (qʷⁱ) rather than to rime. Uses the same collection kernel as rain riming. See Milbrandt et al. (2025).

Returns

  • Rain mass rate collected onto ice [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.refreezing_rate — Method
refreezing_rate(
    p3,
    qⁱ,
    qʷⁱ,
    nⁱ,
    T,
    qᵛ,
    Fᶠ,
    ρᶠ,
    ρ,
    ρᵗʰ,
    constants,
    transport
)

Compute refreezing rate of liquid on ice using the heat-balance formula.

Below freezing, liquid coating on ice particles refreezes. The rate is determined by the heat flux at the particle surface, Cholette et al. (2019), Eq. (A5):

\[\frac{dm}{dt} = \frac{2π}{ℒᶠʳ} C f^{ve} \left[Kᵃ(T_0-T) + ρ ℒⁱ Dᵛ (q^{v+}_0 - q^v)\right]\]

The conduction and vapor terms are those of wet_growth_capacity, but the coating is already at T₀, so there is no drop-warming term. The capacity is capped by the liquid available on the ice; above freezing it is zero, which carries the temperature gate here.

Arguments

  • p3: P3 microphysics scheme
  • qⁱ: Ice mass fraction [kg/kg]
  • qʷⁱ: Liquid water on ice [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • T: Temperature [K]
  • qᵛ: Vapor mass fraction [kg/kg]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Total density, weighting the vapor-diffusion flux [kg/m³]
  • ρᵗʰ: Thermodynamic state density, at which the freezing-point saturation fraction is evaluated [kg/m³]
  • constants: Thermodynamic constants
  • transport: Pre-computed air transport properties (; Dᵛ, Kᵃ, ν)

Returns

  • Rate of liquid → ice refreezing [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.rime_density — Method
rime_density(
    p3,
    qᶜˡ,
    cloud_rim,
    T,
    𝕎ⁱ,
    ρ,
    constants,
    transport,
    μᶜˡ,
    λᶜˡ
)

Compute the density of newly accreted cloud rime from the rime-impact parameter.

Take the already-diagnosed cloud gamma PSD parameters μᶜˡ and λᶜˡ, compute the droplet impact speed relative to falling ice, form the rime-impact parameter Ri, and apply the piecewise density fit of Cober and List (1993). When cloud riming is inactive or the air is above freezing, the fallback value 400 kg m⁻³ is used.

Arguments

  • p3: P3 microphysics scheme
  • qᶜˡ: Cloud liquid mass fraction [kg/kg]
  • cloud_rim: Cloud-riming mass tendency [kg/kg/s]
  • T: Temperature [K]
  • 𝕎ⁱ: Ice particle fall speed [m/s]
  • ρ: Air density [kg/m³]
  • constants: Thermodynamic constants
  • transport: Air transport properties at (T, P)
  • μᶜˡ, λᶜˡ: Cloud gamma PSD shape and slope parameters, diagnosed upstream

Returns

  • Rime density [kg/m³]
source
Breeze.Microphysics.PredictedParticleProperties.rime_splintering_rates — Method
rime_splintering_rates(
    p3,
    cloud_riming,
    rain_riming,
    T,
    D_ice,
    Fˡ,
    surface_T,
    qᶠ
) -> Tuple{Any, Any, Any}

Compute secondary ice production from rime splintering (Hallett-Mossop effect).

When rimed ice particles accrete supercooled drops, ice splinters are ejected. This occurs only in a narrow temperature range around -5°C. See Hallett and Mossop (1974).

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • cloud_riming: Cloud droplet riming rate [kg/kg/s]
  • rain_riming: Rain riming rate [kg/kg/s]
  • T: Temperature [K]
  • D_ice: Mean ice diameter [m]
  • Fˡ: Liquid fraction on ice [-]
  • surface_T: Surface-temperature proxy for the warm-season shutoff [K]
  • qᶠ: Existing rimed-ice mass [kg/kg]

Returns

  • Tuple (qᶜˡsplinteringrate, qʳsplinteringrate, nsplinteringrate): the cloud- and rain-branch ice mass rates [kg/kg/s] and the total number rate [1/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.shedding_rate — Method
shedding_rate(
    p3,
    qʷⁱ,
    nⁱ,
    Fᶠ,
    Fˡ,
    lookups::Breeze.Microphysics.PredictedParticleProperties.P3IceLookups
)

Compute liquid shedding rate from ice particles following Milbrandt et al. (2025).

PSD-integrated shedding of liquid from mixed-phase ice particles with D ≥ 9 mm (Rasmussen et al. 2011):

\[q_{lshd} = F^f \times f_{1pr28} \times N^i \times F^l\]

where f1pr28 = ∫_{D≥9mm} m(D) N'(D) dD (lookup table, Fl-blended mass), Fr = qirim / (qitot - qiliq) is the rime fraction of ice-only mass, and Fl = qiliq / qitot is the liquid fraction.

Arguments

  • p3: P3 microphysics scheme (provides shedding table)
  • qʷⁱ: Liquid water on ice [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • Fᶠ: Rime fraction (= qᶠ/qⁱ) [-]
  • Fˡ: Liquid fraction (= qʷⁱ/(qⁱ+qʷⁱ)) [-]
  • lookups: P3IceLookups of the population

Returns

  • Rate of liquid → rain shedding [kg/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.sink_limiting_factor — Method
sink_limiting_factor(total_sink, available_mass, dt_safety)

Compute proportional rescaling factor for sink rates so that total_sink × dt_safety does not exceed available_mass.

Returns 1 when sinks are within budget, or available_mass / (total_sink × dt_safety) when they exceed it. All arguments must be positive or zero. GPU-compatible: uses ifelse instead of branching.

source
Breeze.Microphysics.PredictedParticleProperties.stochastic_immersion_freezing — Method
stochastic_immersion_freezing(
    p3,
    q,
    n_for_mass,
    n_for_rate,
    μ,
    T
) -> Tuple{Any, Any}

Barklie and Gokhale (1959) stochastic immersion freezing, shared by the cloud and rain paths.

The per-drop freezing probability is J₀ times the drop volume times exp(a ΔT), evaluated on a monodisperse drop of mass q / n_for_mass. For a gamma PSD the mass (6th moment) rate carries the correction $C(μ) = Γ(μ+7)Γ(μ+1)/Γ(μ+4)²$; the number (3rd moment) rate does not.

Arguments

  • p3: P3 microphysics scheme (provides parameters)
  • q: Condensate mass fraction [kg/kg]
  • n_for_mass: Number per unit mass used for the monodisperse drop mass [1/kg]; floored, so the drop mass stays finite where the population vanishes
  • n_for_rate: Number per unit mass the number rate scales with [1/kg]. Cloud passes the floored number here as well; rain passes the unfloored one, so a vanishing rain population produces no number rate
  • μ: PSD shape parameter [-]
  • T: Temperature [K]

Returns

  • Tuple (frozen_mass_rate, frozen_number_rate): mass rate [kg/kg/s] and number rate [1/kg/s]
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρbᶠ — Method
tendency_ρbᶠ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ,
    Fᶠ,
    ρᶠ,
    qⁱ,
    parameters
)

Compute rime volume tendency from P3 process rates.

Rime volume changes with rime mass: ∂bᶠ/∂t = ∂qᶠ/∂t / ρ_rime. Includes sublimation loss: sublimation removes rime volume proportionally. Includes melt-densification: during melting, low-density rime portions melt preferentially, driving the remaining rime toward the configured solid-ice density.

source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρnʳ — Method
tendency_ρnʳ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ,
    p3
)

Compute rain number tendency from P3 process rates.

Rain number gains from:

  • Autoconversion (Phase 1)
  • Complete melting (Phase 1) - new rain drops from melted ice
  • Breakup (Phase 1) - large drops fragment into smaller ones
  • Shedding (Phase 2)
  • Shed drops from above-freezing cloud collection

Rain number loses from:

  • Self-collection (Phase 1)
  • Evaporation (Phase 1) - proportional number removal
  • Riming (Phase 2)
  • Immersion freezing (Phase 2)
  • Homogeneous freezing (Phase 2, T < -40°C)
  • Rain warm collection number
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρnᶜˡ — Method
tendency_ρnᶜˡ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ,
    Nᶜˡ,
    qᶜˡ,
    p3
)

Compute cloud-number tendency from P3 process rates.

Activation creates new cloud droplets. Autoconversion, accretion, riming, freezing, and above-freezing collection remove cloud droplets in proportion to the cloud mass they consume.

source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρnⁱ — Method
tendency_ρnⁱ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ
)

Compute ice number tendency from P3 process rates.

Ice number gains from:

  • Deposition nucleation (Phase 2)
  • Immersion freezing of cloud/rain (Phase 2)
  • Rime splintering (Phase 2)
  • Homogeneous freezing of cloud/rain (Phase 2, T < -40°C)

Ice number loses from:

  • Melting (Phase 1)
  • Sublimation and coating evaporation (Phase 1)
  • Aggregation (Phase 2)
  • Global number limiter

The λ-limiter write-back ice_number_correction is added separately and is signed: it raises nⁱ where the tabulated lower bound binds and lowers it where the upper bound does.

source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρqʳ — Method
tendency_ρqʳ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ
)

Compute rain mass tendency from P3 process rates.

Rain gains from:

  • Autoconversion (Phase 1)
  • Accretion (Phase 1)
  • Complete melting (Phase 1) - meltwater that sheds from ice
  • Shedding (Phase 2) - liquid coating shed from ice (D ≥ 9 mm)
  • Wet growth shedding - excess collection beyond freezing capacity

Rain loses from:

  • Evaporation (Phase 1)
  • Riming (Phase 2)
  • Immersion freezing (Phase 2)
  • Homogeneous freezing (Phase 2, T < -40°C)
  • Rain warm collection by ice (T > T₀) → qʷⁱ
  • Wet growth rain rerouting → qʷⁱ
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρqʷⁱ — Method
tendency_ρqʷⁱ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ
)

Compute liquid on ice tendency from P3 process rates.

Following Milbrandt et al. (2025), the full budget is:

\[\frac{dq^{wi}}{dt} = q_{melt,partial} + q_{ccoll} + q_{rcoll} + q_{wgrth1c} + q_{wgrth1r} + q_{cond,coat} - q_{lshd} - q_{ifrz} - q_{evap,coat} - q_{wgrth,shd}\]

Gains from:

  • Partial melting (meltwater stays on ice as liquid coating)
  • Above-freezing cloud collection (qccoll: T > T₀, cloud → qʷⁱ)
  • Above-freezing rain collection (qrcoll: T > T₀, rain → qʷⁱ)
  • Wet growth cloud rerouting (qwgrth1c: excess collection → qʷⁱ)
  • Wet growth rain rerouting (qwgrth1r: excess collection → qʷⁱ)
  • Condensation onto the liquid coating (qcond,coat)

Loses from:

  • Shedding (liquid sheds to rain from D ≥ 9 mm particles)
  • Refreezing (liquid refreezes to rime)
  • Evaporation from the liquid coating (qevap,coat)
  • Wet growth shedding (qwgrth,shd: excess wet-growth mass diverted to rain)
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρqᵛ — Method
tendency_ρqᵛ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ
)

Compute vapor mass tendency from P3 process rates.

Vapor is consumed by:

  • Condensation (vapor → cloud liquid)
  • Deposition (vapor → ice)
  • Deposition nucleation (vapor → ice)

Vapor is produced by:

  • Cloud evaporation (negative condensation)
  • Rain evaporation
  • Sublimation (negative deposition)

When vapor_excess = PrognosticVaporExcess(), the G&M one-shot alignment is folded into rates.condensation (the M&G condensation rate plus the G&M contribution, which rates.prognostic_vapor_excess_adjustment also carries separately so it stays inspectable), so vapor and cloud tendencies pick it up automatically when integrated with dt = sink_limiting_timescale. See prognostic_vapor_excess_adjustment.

source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρqᶜˡ — Method
tendency_ρqᶜˡ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ
)

Compute cloud liquid mass tendency from P3 process rates.

Cloud liquid gains from:

  • Condensation (Phase 1)

Cloud liquid is consumed by:

  • Autoconversion (Phase 1)
  • Accretion by rain (Phase 1)
  • Riming by ice (Phase 2)
  • Immersion freezing (Phase 2)
  • Homogeneous freezing (Phase 2, T < -40°C)
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρqᶠ — Method
tendency_ρqᶠ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ,
    Fᶠ
)

Compute rime mass tendency from P3 process rates.

Rime mass gains from:

  • Cloud riming (Phase 2)
  • Rain riming (Phase 2)
  • Refreezing (Phase 2)
  • Immersion freezing (frozen cloud/rain becomes rimed ice) (Phase 2)
  • Homogeneous freezing (frozen cloud/rain deposits as dense rime) (Phase 2, T < -40°C)

Rime mass loses from:

  • Melting (proportional to rime fraction) (Phase 1)
  • Sublimation (proportional to rime fraction) (Phase 1)
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρqⁱ — Method
tendency_ρqⁱ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ
)

Compute ice mass tendency from P3 process rates.

Ice gains from:

  • Deposition (Phase 1)
  • Cloud riming (Phase 2)
  • Rain riming (Phase 2)
  • Refreezing (Phase 2)
  • Deposition nucleation (Phase 2)
  • Immersion freezing of cloud/rain (Phase 2)
  • Rime splintering (Phase 2)
  • Homogeneous freezing of cloud/rain (Phase 2, T < -40°C)

Ice loses from:

  • Partial melting (Phase 1) - becomes liquid coating
  • Complete melting (Phase 1) - sheds to rain
source
Breeze.Microphysics.PredictedParticleProperties.tendency_ρδqᵛ⁺ˡ — Method
tendency_ρδqᵛ⁺ˡ(
    rates::Breeze.Microphysics.PredictedParticleProperties.P3ProcessRates,
    ρ,
    parameters
)

Compute the tendency of the vapor excess over liquid from Grabowski & Morrison (2008).

When vapor_excess = PrognosticVaporExcess(), the vapor excess over liquid $δqᵛ⁺ˡ = qᵛ - qᵛ⁺ˡ$ is a prognostic variable advected by the dynamical core. Its microphysical tendency has two parts. The phase-change part reproduces the post-step diagnosis $δqᵛ⁺ˡ = qᵛ - qᵛ⁺ˡ(T)$ from the final local $qᵛ$ and $T$ implied by the ordered process rates. The external part, $-∂ₜqᵛ⁺ˡ$ from adiabatic cooling and expansion (see external_vapor_excess_forcing), keeps the prognostic consistent with the host state, so the G&M alignment only corrects transport and other unrepresented forcing.

When vapor_excess = DiagnosticVaporExcess(), returns zero tendency.

source
Breeze.Microphysics.PredictedParticleProperties.ventilation_sc_correction — Method
ventilation_sc_correction(ν, Dᵛ, ρ_correction, floors)

Schmidt number correction factor for ventilation-enhanced table values.

The P3 lookup table stores the ventilation-enhanced integral without the Sc^{1/3} √ρ_correction / √ν factor. This function computes the correction that must be applied at runtime:

\[f_{Sc} = \frac{Sc^{1/3} \sqrt{\rho_{fac}}}{\sqrt{\nu}}\]

See rain_quadrature.jl for the table storage convention.

source
Breeze.Microphysics.PredictedParticleProperties.wet_growth_capacity — Function
wet_growth_capacity(
    p3,
    qⁱ,
    qʷⁱ,
    nⁱ,
    T,
    qᵛ,
    Fᶠ,
    ρᶠ,
    ρ,
    ρᵗʰ,
    constants,
    transport,
    lookups=p3_ice_lookups(p3, qⁱ, qʷⁱ, nⁱ, Fᶠ, ρᶠ, ρ)
)

Compute the wet growth freezing capacity following Musil (1970), Eq. (A9), as in P3 v4.

The wet growth capacity is the maximum rate at which collected hydrometeors can be frozen. Collected drops are warmed from T to T₀ and freeze at a wet surface, so the heat balance uses the vaporization and fusion latent heats at T₀:

\[\dot{q}_\text{wet} = 2π C f^{ve} \frac{Kᵃ(T_0-T) + ℒˡ_0 Dᵛ(ρ^{v+}_0-ρ^v)}{ℒᶠʳ_0 + cˡ (T - T_0)} × N^i\]

When the collection rate (cloud + rain riming) exceeds this capacity, the excess collected water stays liquid and is redirected into qʷⁱ.

Arguments

  • p3: P3 microphysics scheme
  • qⁱ: Ice mass fraction [kg/kg]
  • qʷⁱ: Liquid water on ice mass fraction [kg/kg]
  • nⁱ: Ice number concentration [1/kg]
  • T: Temperature [K]
  • qᵛ: Vapor mass fraction [kg/kg]
  • Fᶠ: Rime fraction [-]
  • ρᶠ: Rime density [kg/m³]
  • ρ: Total density, weighting the vapor-diffusion flux and the ice lookups [kg/m³]
  • ρᵗʰ: Thermodynamic state density, at which the freezing-point saturation fraction is evaluated [kg/m³]
  • constants: Thermodynamic constants
  • transport: Pre-computed air transport properties (; Dᵛ, Kᵃ, ν)

Returns

  • Wet growth capacity [kg/kg/s] (positive; zero when T ≥ T₀)
source

MoistAirBuoyancies

Breeze.MoistAirBuoyancies.compute_boussinesq_adjustment_temperature — Method
compute_boussinesq_adjustment_temperature(
    𝒰₀::Breeze.Thermodynamics.LiquidIcePotentialTemperatureState{FT},
    constants::ThermodynamicConstants
) where FT

Return the temperature $T$ corresponding to thermodynamic equilibrium between the specific humidity and liquid mass fractions of the input thermodynamic state 𝒰₀, wherein the specific humidity is equal to or less than the saturation specific humidity at the given conditions and affiliated with theromdynamic constants constants.

The saturation equilibrium temperature satisfies the nonlinear relation

\[ĉᵖ Π θ = cᵖᵐ T - ℒˡ₀ qˡ ,\]

with $ℒˡ₀$ the latent heat of condensation extrapolated to absolute zero, $cᵖᵐ$ the mixture heat capacity, $ĉᵖ$ the vapor-equivalent heat capacity, $Π$ the Exner function, $qˡ = \max(0, qᵗ - qᵛ⁺)$ the condensate specific humidity, $qᵗ$ is the total specific humidity, and $qᵛ⁺$ is the saturation specific humidity.

The saturation equilibrium temperature is thus obtained by solving $r(T) = 0$, where

\[r(T) ≡ T - (ĉᵖ Π θ + ℒˡ₀ qˡ) / cᵖᵐ .\]

Solution of $r(T) = 0$ is found via the secant method.

source

ParcelModels

Breeze.ParcelModels.check_domain_bounds! — Method
check_domain_bounds!(state, grid)

Check that the parcel remains within the vertical grid domain [0, Lz].

Throws an error if the parcel escapes the domain, since extrapolation of environmental profiles (pressure, density) beyond the grid is unphysical.

source
Breeze.ParcelModels.initialize_parcel_state! — Method
initialize_parcel_state!(state, z₀, x₀, y₀, model)

Initialize the parcel state by interpolating environmental conditions at the given position. The thermodynamic variable is initialized at the environmental temperature with the condensate carried by the microphysical prognostics.

source
Breeze.ParcelModels.set_moisture_from_relative_humidity! — Method
set_moisture_from_relative_humidity!(
    qᵗ_field,
    ℋ,
    T_field,
    ρ_field,
    constants
)

Set specific humidity field from relative humidity, computing

\[qᵗ = ℋ qᵛ⁺(T, ρ).\]

where $qᵗ$ is the total specific moisture, $ℋ$ is the relative humidity, and $qᵛ⁺$ is the saturation specific humidity at temperature $T$ and density $ρ$.

source
Breeze.ParcelModels.set_parcel_aerosol_number — Method
set_parcel_aerosol_number(μ, microphysics, ρ, nᵃ, ρnᵃ)

Return μ with its aerosol reservoir ρnᵃ [m⁻³] set from the parcel's environmental density ρ: to ρ * nᵃ if nᵃ [kg⁻¹] is given, to ρnᵃ if that is given, and otherwise to the scheme default AtmosphereModels.initial_aerosol_number_density.

Schemes without a prognostic reservoir have no ρnᵃ to set, so μ is returned unchanged; supplying nᵃ or ρnᵃ for one of those is an ArgumentError rather than a silent no-op.

Because set! calls this on every invocation, a later set! also resets the reservoir to the distribution default. Pass nᵃ or ρnᵃ explicitly to carry a depleted reservoir across a set!.

source
Breeze.ParcelModels.set_temperature_from_potential_temperature! — Method
set_temperature_from_potential_temperature!(
    T_field,
    θ,
    p_field,
    qᵛ_field,
    pˢᵗ,
    constants
)

Set temperature field from potential temperature, using proper thermodynamic relations.

The moisture field qᵛ_field supplies the mixture gas constant and heat capacity that define the Exner function, so a moist column converts $θ → T$ with $Rᵐ / cᵖᵐ$ rather than the dry exponent. Moisture is taken to be all vapor, the same no-condensate assumption the rest of set! makes before microphysics repartitions the water.

source
Breeze.ParcelModels.ssp_rk3_microphysics_substep — Method
ssp_rk3_microphysics_substep(
    ::Nothing,
    ρ⁰,
    ::Nothing,
    ρᵐ,
    ::Nothing,
    Δt,
    α,
    ρ⁺
)

Apply SSP RK3 substep formula to microphysics prognostic variables.

The stored moments μ are density-weighted, while a parcel conserves their specific counterparts μ / ρ in the absence of microphysical sources. Each RK branch is therefore converted to its specific value before combining, then weighted by the new environmental density ρ⁺.

source
Oceananigans.Fields.set! — Method
set!(
    model::AtmosphereModel{<:ParcelDynamics};
    T=nothing,
    θ=nothing,
    ρ=nothing,
    p=nothing,
    qᵗ=nothing,
    ℋ=nothing,
    u=0,
    v=0,
    w=0,
    w_parcel=nothing,
    x=0,
    y=0,
    z=nothing,
    nᵃ=nothing,
    ρnᵃ=nothing
)

Set the environmental profiles and initial parcel state for a ParcelModel.

Environmental profiles are set on the model's fields (temperature, density, pressure, velocities). The parcel is initialized at the specified position with environmental conditions interpolated at that height.

Keyword Arguments

Thermodynamic profiles (provide one of T or θ):

  • T: Temperature profile T(z) [K] - function, array, Field, or constant
  • θ: Potential temperature profile θ(z) [K] - function, array, or constant. If provided, T is computed from θ and p using thermodynamic relations.
  • ρ: Density profile ρ(z) [kg/m³] - function, array, Field, or constant
  • p: Pressure profile p(z) [Pa] - function, array, Field, or constant

Moisture (provide one of qᵗ or ℋ):

  • qᵗ: Specific humidity profile qᵗ(z) [kg/kg] - function, array, or constant (default: 0)
  • ℋ: Relative humidity profile ℋ(z) [0-1] - function, array, or constant. If provided, qᵗ is computed as qᵗ = ℋ * qᵛ⁺(T, ρ).

The parcel's thermodynamic variable is initialized at the environmental temperature with the condensate carried by its microphysical prognostics. Saturation adjustment then equilibrates the state at fixed static energy or liquid–ice potential temperature.

Velocities:

  • u: Zonal velocity u(z) [m/s] - function, array, or constant (default: 0)
  • v: Meridional velocity v(z) [m/s] - function, array, or constant (default: 0)
  • w: Vertical velocity w(z) [m/s] - function, array, or constant (default: 0)

Parcel state:

  • x: Initial parcel x-position [m], default: 0
  • y: Initial parcel y-position [m], default: 0
  • z: Initial parcel height [m], required to initialize parcel state
  • w_parcel: Initial parcel vertical velocity [m/s], for PrognosticVerticalVelocity
  • nᵃ: Initial aerosol number per unit mass [kg⁻¹], for a scheme that carries a prognostic reservoir. Defaults to the value implied by the scheme's aerosol distribution, so a depleted reservoir must be passed explicitly to survive a set! (see set_parcel_aerosol_number)
  • ρnᵃ: Initial aerosol number density [m⁻³], the ρ-weighted alternative to nᵃ
source
Oceananigans.TimeSteppers.time_step! — Method
time_step!(
    model::AtmosphereModel{<:ParcelDynamics, <:Any, <:Any, <:SSPRungeKutta3},
    Δt;
    callbacks=nothing
)

Advance the parcel model by one time step $Δt$ using SSP RK3.

The SSP RK3 scheme Shu and Osher (1988) is:

\[\begin{align*} u^{(1)} &= u^{(0)} + Δt \, G(u^{(0)}) \\ u^{(2)} &= \frac{3}{4} u^{(0)} + \frac{1}{4} u^{(1)} + \frac{1}{4} Δt \, G(u^{(1)}) \\ u^{(3)} &= \frac{1}{3} u^{(0)} + \frac{2}{3} u^{(2)} + \frac{2}{3} Δt \, G(u^{(2)}) \end{align}\]

This scheme has CFL coefficient = 1 and is TVD (total variation diminishing).

source
Oceananigans.TimeSteppers.update_state! — Function
update_state!(
    model::AtmosphereModel{<:ParcelDynamics},
    callbacks=[];
    compute_tendencies=true
)

Update the parcel model state, computing tendencies and auxiliary variables.

This function is called at the beginning of each time step and after each substep in multi-stage time steppers. It mirrors the role of update_state! for AtmosphereModel and consolidates all state-dependent computations:

  1. Compute position tendencies (Gx, Gy, Gz) from environmental velocity profiles
  2. Any other auxiliary state computations (currently none)

Keyword Arguments

  • compute_tendencies: If true (default), compute tendencies for prognostic variables.
source

PotentialTemperatureFormulations

Breeze.AtmosphereModels.set_thermodynamic_variable! — Method
set_thermodynamic_variable!(
    model::AtmosphereModel{<:Any, <:LiquidIcePotentialTemperatureFormulation},
    ::Val{:T},
    value
)

Set the thermodynamic state from in-situ temperature $T$.

The temperature is converted to liquid-ice potential temperature θˡⁱ using the relation between $T$ and θˡⁱ` that accounts for the moisture distribution.

For unsaturated air (no condensate), this simplifies to $θ = T / Π$ where $Π$ is the Exner function.

source
Breeze.AtmosphereModels.static_energy_density — Method
static_energy_density(
    model::AtmosphereModel{<:Any, <:LiquidIcePotentialTemperatureFormulation}
) -> Field{LX, LY, LZ, O, G, I, D, T, B, Oceananigans.Fields.FieldStatus{Float64}} where {LX, LY, LZ, O, G, I, D, T, B}

Return the static energy density as a Field with boundary conditions that return energy fluxes when used with BoundaryConditionOperation.

For LiquidIcePotentialTemperatureFormulation, the prognostic variable is potential temperature density ρθ. This function converts the ρθ boundary conditions to energy flux boundary conditions by multiplying by $ĉᵖ Π$, the inverse of $∂θˡⁱ/∂h$.

source
Breeze.PotentialTemperatureFormulations.sedimentation_thermal_response — Method
sedimentation_thermal_response(
    dynamics,
    κ̂,
    q,
    constants,
    T,
    Π
) -> Tuple{Tuple{Any, Any}, Any}

Return the transported liquid/ice enthalpies and local potential-temperature heating response. With a fixed total density (the default) the departed condensate mass is made up by dry air at prescribed pressure: transport hˣ − hᵈ, the enthalpy change along the composition increment, and respond with 1 / (ĉᵖ Π). CompressibleDynamics transports phase enthalpy hˣ and uses β_cv for isolated sedimentation at fixed volume and gas partial densities, without phase change or resolved motion. These instantaneous responses do not reconstruct finite-step energy.

This callback serves the liquid-ice potential-temperature formulation. The compressible temperature_and_pressure diagnosis supports that formulation, not StaticEnergyFormulation; this sedimentation correction does not add a compressible static-energy diagnosis.

source

RoundingTreatments

Breeze.RoundingTreatments.TwoSum — Type
struct TwoSum

Stochastic rounding of a sum in its own precision: TwoSum gives the exact rounding error $e$, and the sum moves to the neighboring float in the direction of $e$ with probability $|e| / \text{gap}$. The default on GPUs, where Float64 arithmetic is slow or unavailable.

source
Breeze.RoundingTreatments.WidenedSum — Type
struct WidenedSum

Stochastic rounding of a Float32 sum by computing it in Float64, adding random bits below the 24 bits of the Float32 significand, and truncating toward zero. Other precisions fall back to TwoSum. The default on CPUs.

source
Breeze.RoundingTreatments.rounded_add — Method
rounded_add(::RoundToNearest, a, b, i, j, k, key)

Return $a + b$ rounded according to the round-off treatment. i, j, k and key (from rounding_key) seed the random number of StochasticRounding.

julia> using Breeze.RoundingTreatments: rounded_add, rounding_keyjulia> u⁰, δ = 300f0, 1f-5;  # δ is a third of the gap between u⁰ and nextfloat(u⁰)julia> rounded_add(RoundToNearest(), u⁰, δ, 1, 1, 1, UInt32(0))300.0f0julia> rounding = StochasticRounding(seed = 1);julia> key = rounding_key(rounding, 0, 1, 1);julia> sums = [rounded_add(rounding, u⁰, δ, i, 1, 1, key) for i in 1:100000];julia> sort(unique(sums))2-element Vector{Float32}: 300.0 300.00003julia> round(sum(Float64, sums .- u⁰) / length(sums), sigdigits = 1)1.0e-5
source
Breeze.RoundingTreatments.rounding_key — Method
rounding_key(
    ::Breeze.RoundingTreatments.AbstractRoundingTreatment,
    iteration,
    stage,
    field
) -> UInt32

Return the 32-bit key that, together with the grid indices, determines the random numbers of one stage update of one prognostic field (an integer that distinguishes the fields updated in the same stage). The key mixes the seed with iteration and stage, so every update draws fresh numbers. RoundToNearest draws none and returns zero without reading its arguments.

source

SingleColumnMode

Solvers

Breeze.Solvers.newton_solve — Method
newton_solve(
    residual_and_derivative,
    solver::NewtonSolver,
    x
)

Solve r(x) = 0 by Newton iteration from initial guess x, where residual_and_derivative(x) returns the tuple (r(x), r′(x)).

The iteration is controlled by solver:

  • NewtonSolver: iterate until |Δx| ≤ max(abstol, reltol * |x|) or maxiter is reached
  • FixedIterations: perform exactly iterations Newton steps (no convergence test)
  • nothing: return the initial guess x unmodified
using Breezeusing Breeze.Solvers: newton_solvesolver = NewtonSolver(reltol=1e-12, maxiter=20)x = newton_solve(x -> (x^2 - 2, 2x), solver, 1.0)round(x, digits=10)# output1.4142135624
source
Breeze.Solvers.secant_solve — Method
secant_solve(residual, solver::SecantSolver, x₁, x₂, scale)

Solve r(x) = 0 by secant iteration from the initial guesses x₁ and x₂, where residual(x) returns r(x). The convergence criterion compares the residual against scale: iteration stops when |r| ≤ max(abstol, reltol * |scale|, 30 eps(scale)), where the last term is the residual's rounding noise (see the tolerance conventions in Solvers).

The iteration is controlled by solver:

  • SecantSolver: iterate until the residual converges or maxiter is reached
  • FixedIterations: perform exactly iterations secant steps (no convergence test)

A degenerate step (r₂ = r₁, slope undefined) terminates a SecantSolver iteration at the current iterate and leaves a FixedIterations iterate unchanged.

using Breezeusing Breeze.Solvers: secant_solvesolver = SecantSolver(abstol=1e-12, maxiter=20)x = secant_solve(x -> x^2 - 2, solver, 1.0, 2.0, 1.0)round(x, digits=10)# output1.4142135624
source

StaticEnergyFormulations

TerrainFollowingDiscretization

Breeze.TerrainFollowingDiscretization.terrain_wall_heights — Method
terrain_wall_heights(
    x,
    y,
    grid::Oceananigans.Grids.AbstractUnderlyingGrid{<:Any, <:Any, <:Any, <:Bounded, <:TerrainFollowingVerticalDiscretization}
) -> Tuple{Any, Any}

Return the physical altitudes (z_bottom, z_top) of the bounding coordinate surfaces above the horizontal position (x, y): the terrain surface z(x, y, r_bottom) and the lid z(x, y, r_top). These are the walls a particle bounces off, and they are evaluated with the same interpolated terrain components as terrain_reference_coordinate, so a particle sitting exactly on either wall inverts to exactly r_bottom or r_top.

source

Thermodynamics

Breeze.Thermodynamics.AbstractExnerExponent — Type
abstract type AbstractExnerExponent

Abstract supertype for the exponent $κ$ of the Exner function $Π = (p / pˢᵗ)^κ$ that defines the liquid-ice potential temperature $θˡⁱ$. Subtypes are VaporEquivalentExponent and DryExponent; both make $κ$ independent of how water is split between vapor and condensate, so a phase change at fixed $θˡⁱ$, pressure, and total water conserves enthalpy exactly.

source
Breeze.Thermodynamics.bottom_face_height — Method
bottom_face_height(grid)

Height of the bottom face of column (1, 1), the level at which a height-coordinate reference state is anchored. Zero for the usual domain that starts at the ground.

source
Breeze.Thermodynamics.column_reference_state — Method
column_reference_state(
    grid,
    constants,
    base_pressure,
    potential_temperature,
    pˢᵗ,
    discrete_hydrostatic_balance,
    vapor_mass_fraction,
    liquid_mass_fraction,
    ice_mass_fraction
) -> ReferenceState{<:Any, SP, SD, STm, P, D, T, QV, QL, QI} where {SP<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), SD<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), STm<:(Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), P<:(Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), D<:(Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), T<:(Field{Center, Center, Center, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}), QV<:(Oceananigans.Fields.ZeroField{T, 3} where T), QL<:(Oceananigans.Fields.ZeroField{T, 3} where T), QI<:(Oceananigans.Fields.ZeroField{T, 3} where T)}

Construct a per-column ReferenceState on a column-ensemble grid, where base_pressure and/or potential_temperature are (Nx, Ny) arrays supplying one adiabatic profile per column. Scalars are shared across all columns. The reference fields (ρᵣ, pᵣ, Tᵣ) then vary column-by-column; the scalar base_pressure/potential_temperature metadata store the first column's surface values.

source
Breeze.Thermodynamics.converge_by_step_doubling — Method
converge_by_step_doubling(
    integrate,
    y₀,
    z,
    tolerance,
    initial_steps,
    max_steps
)

Evaluate integrate(nsteps) with the step count repeatedly doubled from initial_steps, returning the first refinement whose value changes by less than the relative tolerance. Returns y₀ unchanged when z == 0.

Shared by both hydrostatic reductions from the $z = 0$ datum, which differ only in their stepper: midpoint_integral when the integrand depends on height alone, and runge_kutta2_integral when it also depends on the pressure being solved for.

Warns rather than returning silently if max_steps is reached without converging: an unconverged reduction would otherwise anchor a whole reference profile at a wrong ground pressure with no indication.

source
Breeze.Thermodynamics.converged_hydrostatic_pressure — Method
converged_hydrostatic_pressure(
    z,
    p₀,
    dpdz;
    tolerance=sqrt(eps(float(typeof(p₀)))),
    initial_steps=16,
    max_steps=1 << 16
)

Integrate the hydrostatic equation $∂p/∂z = \mathrm{dpdz}(z, p)$ from $z = 0$ to height $z$, repeatedly doubling the number of steps until the pressure at $z$ changes by less than the relative tolerance between successive refinements. dpdz(z, p) returns the local pressure gradient $-g ρ$ given height and pressure.

source
Breeze.Thermodynamics.enforce_discrete_hydrostatic_balance! — Method
enforce_discrete_hydrostatic_balance!(pᵣ, ρᵣ, grid, g)

Recompute the reference pressure pᵣ from the reference density ρᵣ by discrete upward integration, ensuring that the discrete hydrostatic balance

\[\frac{p_{ref}[k] - p_{ref}[k-1]}{Δz} + g \frac{ρ_{ref}[k] + ρ_{ref}[k-1]}{2} = 0\]

holds exactly at every interior z-face. This guarantees that reference-state subtraction in the pressure gradient and buoyancy cancels to machine precision, eliminating the $O(Δz^2)$ truncation error that would otherwise dominate the momentum tendency for nearly-hydrostatic flows.

source
Breeze.Thermodynamics.exner_exponent — Method
exner_exponent(::VaporEquivalentExponent, q, constants)

Return the value $κ$ of the Exner exponent for moisture mass fractions q: $κ̂ = R̂ / ĉᵖ$ for VaporEquivalentExponent and $κᵈ = Rᵈ / cᵖᵈ$ for DryExponent.

Example

using Breezeusing Breeze.Thermodynamics: exner_exponent, MoistureMassFractionsconstants = ThermodynamicConstants()q = MoistureMassFractions(0.012, 0.0, 0.0)exner_exponent(VaporEquivalentExponent(), q, constants), exner_exponent(DryExponent(), q, constants)# output(0.2847851886054834, 0.2855746334945912)
source
Breeze.Thermodynamics.hydrostatic_pressure — Method
hydrostatic_pressure(z, p₀, θ₀::Number, pˢᵗ, constants)

Dry hydrostatic pressure at height z, reduced from the datum p₀ at $z = 0$ along the reference potential temperature, with pˢᵗ the standard pressure of the Exner function.

The potential temperature selects how the reduction is carried out: a constant θ₀ has the closed form adiabatic_hydrostatic_pressure, while a profile θᵣ(z) is integrated numerically by numerically_integrated_hydrostatic_pressure. hydrostatic_density and hydrostatic_temperature dispatch the same way.

source
Breeze.Thermodynamics.is_column_reference — Method
is_column_reference(ref)

Whether ref stores a single reference column broadcast to every (i, j), as opposed to genuinely column-dependent 3D fields. Selects between the single-column and per-column integration kernels on a reset. The field dimensions provide this information directly without relying on the values in surface_pressure.

source
Breeze.Thermodynamics.midpoint_integral — Method
midpoint_integral(z, y₀, dydz, nsteps)

Midpoint quadrature of $∂y/∂z = \mathrm{dydz}(z)$ from $0$ to z in nsteps steps, for an integrand that depends on height alone.

source
Breeze.Thermodynamics.moist_hydrostatic_pressure — Function
moist_hydrostatic_pressure(
    z,
    p₀,
    θᵣ,
    ::Nothing,
    pˢᵗ,
    constants,
    κ̂=VaporEquivalentExponent()
)

Continuous hydrostatic pressure at physical height z, reduced from the datum p₀ at $z = 0$ along the reference profiles θᵣ and qᵛᵣ. A dry reference (qᵛᵣ = nothing) falls through to hydrostatic_pressure, which has a closed form for constant θᵣ; a constant moist reference (θᵣ and qᵛᵣ both numbers) has one too, and uses it.

This is the one place the $z = 0$ datum is converted into a pressure at some other height. Both reference-state families use it to obtain the anchor at the bottom face of a column: the terrain surface on a terrain-following grid, the domain bottom on a height-coordinate grid. It returns p₀ exactly when z == 0. The Exner exponent κ̂ relating θᵣ to temperature defaults to VaporEquivalentExponent(); pass the model's exponent so the anchor lies on the column that set_to_mean! integrates. A dry reference is independent of the exponent.

source
Breeze.Thermodynamics.numerically_integrated_hydrostatic_pressure — Method
numerically_integrated_hydrostatic_pressure(
    z,
    p₀,
    θ_func,
    pˢᵗ,
    constants
)

Compute the dry hydrostatic pressure at height $z$ by numerically integrating $∂p/∂z = -g ρ$ from $z=0$, where $ρ = p/(Rᵈ T)$ and $T = θ(z) (p/pˢᵗ)^κ$.

This function handles non-uniform potential temperature profiles $θ(z)$ for which the closed-form adiabatic solution does not apply. The integration is carried out in the dry Exner function $Π = (p / pˢᵗ)^κ$, which satisfies the linear equation $∂Π/∂z = -g / (cᵖᵈ θ(z))$.

source
Breeze.Thermodynamics.reject_renamed_surface_pressure — Method
reject_renamed_surface_pressure(::Nothing)

Reject the old surface_pressure keyword, which named the reference pressure datum at $z = 0$ and is now base_pressure.

Worth an explicit error rather than a MethodError, because the name was not retired: it now names the pressure at a column's bottom face, which is derived from base_pressure and the grid rather than set by the user, and which differs from the datum by $O(ρgh)$ whenever the ground is not at $z = 0$. A caller who moved an old script across would otherwise have no hint that the quantity they meant is spelled differently now, nor that the spelling they used means something else.

source
Breeze.Thermodynamics.runge_kutta2_integral — Method
runge_kutta2_integral(z, y₀, dydz, nsteps)

Explicit midpoint (RK2) integration of $∂y/∂z = \mathrm{dydz}(z, y)$ from $0$ to z in nsteps steps, for an integrand that also depends on the solution.

source
Breeze.Thermodynamics.set_surface_state! — Method
set_surface_state!(field, value)

Write value into a surface field and fill its halos. The halo fill is the load-bearing half: the field is aliased into a ValueBoundaryCondition by surface_boundary_value and read by the column kernels, so a write that skipped it would leave both stale.

source
Breeze.Thermodynamics.surface_boundary_value — Method
surface_boundary_value(
    field::Oceananigans.Fields.AbstractField
) -> Oceananigans.Fields.AbstractField

A surface quantity in the form Oceananigans' boundary conditions expect. A Field{Center, Center, Nothing} already is that form: Oceananigans defines getbc(::ZReducedField, i, j, grid, args...) = condition[i, j, 1] and an Adapt rule that preserves the location of a reduced field, so one can be used as a boundary value directly. The field is therefore passed through rather than wrapped.

Passing the field itself, rather than a view of its interior, is what makes the aliasing hold: a ValueBoundaryCondition built from it reads whatever the field currently contains, so a reference reset that writes new surface values in place updates every boundary condition built from it, with nothing rebuilt.

source
Breeze.Thermodynamics.surface_pressure_from_cell_center — Method
surface_pressure_from_cell_center(p, ρ, Δz, g)

Extrapolate pressure from the first cell center to the bottom face using the local hydrostatic scale height $p / (ρg)$. This provides a live surface pressure from the model state without assuming where the reference-pressure datum is located.

source
Breeze.Thermodynamics.surface_pressure_from_cell_center — Method
surface_pressure_from_cell_center(i, j, k, grid, p, ρ, g)

The same extrapolation, reading the pressure and density fields at (i, j, k). Every consumer of "the live pressure at the bottom face" — the surface fluxes, the diagnostic hydrostatic pressure, and PrescribedDynamics — goes through this one method, so they cannot drift on which level or which half-cell factor they use.

source
Breeze.Thermodynamics.surface_pressure_value — Method
surface_pressure_value(ref)

The bottom-face pressure of ref as a scalar. Only valid for a reference whose bottom-face pressure is horizontally uniform. For a horizontally varying 3D reference or over terrain, ref.surface_pressure must be read as a field.

source
Breeze.Thermodynamics.surface_state_field — Method
surface_state_field(
    grid,
    value
) -> Field{Center, Center, Nothing, Nothing, G, I, D, T, B, Nothing} where {G, I, D, T, B}

A 2D (Center, Center, Nothing) field holding a surface (bottom-face) quantity, initialized to value. Bottom-face quantities are stored in fields rather than as plain scalars so that the ValueBoundaryCondition of the reference pressure/density can point at them once, at construction: a reference reset then writes new boundary values into the field and the boundary condition follows, with no need to rebuild the reference state or its fields. That is what keeps the reference states immutable, and therefore isbits after Adapt, which they must be because the dynamics that owns them is passed directly to GPU kernels.

source
Breeze.Thermodynamics.surface_temperature_value — Method
surface_temperature_value(ref)

The horizontally uniform bottom-face temperature of ref as a scalar. Stored rather than recovered from surface_pressure and surface_density through a gas law, because which gas constant closes that inversion depends on how the reference was built: the constructor's density is dry, while a reset rebuilds it with the mixture constant, so pˢ / (Rᵈ ρˢ) is the temperature in one case and the virtual temperature in the other.

source

TimeSteppers

Breeze.TimeSteppers.acoustic_rk3_substep! — Function
acoustic_rk3_substep!(
    model::AtmosphereModel,
    Δt,
    β,
    rounding=RoundToNearest()
)

Run one Wicker–Skamarock RK3 stage: complete the slow tendencies built by update_state!, then execute the linearized-acoustic substep loop, then update remaining scalars. The stage's updates are rounded with the round-off treatment rounding.

source
Breeze.TimeSteppers.implicit_stage_step! — Method
implicit_stage_step!(model, name, u, Δt)

Apply the vertically-implicit solve of the prognostic u named name over Δt: the first-order upwind remainder of adaptive implicit vertical advection and the vertically-implicit closure diffusion, in one tridiagonal system. A no-op when the time stepper has no implicit solver.

source
Oceananigans.Advection.adaptive_advection_timestep — Method
adaptive_advection_timestep(
    timestepper::AcousticRungeKutta3,
    clock
)

The adaptive-implicit split time step for the next Wicker–Skamarock stage, so the explicit velocity fraction frozen into Gⁿ pairs with the implicit fraction the next stage applies. Stage 1 of step $n$ is evaluated before $Δtₙ$ is known and deliberately uses $β₁ Δtₙ₋₁$; the cost is confined to CFL targeting on one stage when $Δt$ changes (see maybe_prepare_first_time_step! for the cold-start seeding).

source
Oceananigans.TimeSteppers.time_step! — Method
time_step!(
    model::AtmosphereModel{<:Any, <:Any, <:Any, <:SSPRungeKutta3},
    Δt;
    callbacks=[]
)

Step forward model one time step $Δt$ with the SSP RK3 method.

The algorithm is:

\[\begin{align*} u^{(1)} &= u^{(0)} + Δt \, G(u^{(0)}) \\ u^{(2)} &= \frac{3}{4} u^{(0)} + \frac{1}{4} u^{(1)} + \frac{1}{4} Δt \, G(u^{(1)}) \\ u^{(3)} &= \frac{1}{3} u^{(0)} + \frac{2}{3} u^{(2)} + \frac{2}{3} Δt \, G(u^{(2)}) \end{align*}\]

where $G$ above is the right-hand-side, e.g., $∂u/∂t = G(u)$.

The tendencies are evaluated at the Butcher abscissae $c = (0, 1, 1/2)$: $u^{(2)}$ approximates the solution at the midpoint of the step, so the clock steps back by $Δt/2$ after the second stage. This keeps third-order accuracy for a time-dependent right-hand side.

source

TurbulenceClosures

Breeze.TurbulenceClosures.TKEClosureFields — Type
struct TKEClosureFields{K, N, L, KC, LC}

Precomputed fields for TKEBasedTurbulenceClosure: the three diffusivities, the static stability $N²$, the mixing length $ℓ$ and the implicit linear coefficient. Unlike CATKE's, the mixing length is stored, because its nonlocal formulations are computed column by column rather than pointwise; closure_fields.ℓᵐ is the diagnostic of $ℓ$ from the model state.

source
Breeze.TurbulenceClosures._add_tke_tendencies! — Method
_add_tke_tendencies!(
    dev
) -> Union{KernelAbstractions.Kernel{KernelAbstractions.CPU, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, typeof(Breeze.TurbulenceClosures.cpu__add_tke_tendencies!)}, KernelAbstractions.Kernel{Backend, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, typeof(Breeze.TurbulenceClosures.gpu__add_tke_tendencies!)} where Backend<:KernelAbstractions.GPU}

Add the local sources of the TKE equation, $ρ (P + B⁺)$ — shear production, formed from $Kᵘ$ and the velocities at the current Runge–Kutta stage, and the positive part of the buoyancy flux, formed at faces where $Kᶜ$ and $N²$ live and reconstructed to centers — to the tendency of the ρe tracer. Under an explicit time discretization the sinks $ρ Lᵉ e$ are added too.

source
Breeze.TurbulenceClosures._compute_mixing_length! — Method
_compute_mixing_length!(
    dev
) -> Union{KernelAbstractions.Kernel{KernelAbstractions.CPU, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, typeof(Breeze.TurbulenceClosures.cpu__compute_mixing_length!)}, KernelAbstractions.Kernel{Backend, KernelAbstractions.NDIteration.DynamicSize, KernelAbstractions.NDIteration.DynamicSize, typeof(Breeze.TurbulenceClosures.gpu__compute_mixing_length!)} where Backend<:KernelAbstractions.GPU}

Compute the primary mixing length at every face of every column, by the formulation of closure.mixing_length (LocalMinimumMixingLength, IntegralMixingLength or GradientLimitedMixingLength), from the specific turbulent kinetic energy e at the cell centers and the stored static stability N² at the faces. One thread per column.

source
Breeze.TurbulenceClosures.absorb_stratification_coefficient — Method
absorb_stratification_coefficient(
    Cᴺ,
    sf::ConstantStabilityFunctions
) -> Tuple{LocalMinimumMixingLength, ConstantStabilityFunctions}

Convert the parameters of the normalization $ℓ = \min(z, Cᴺ \sqrt{e} / N)$ — a coefficient $Cᴺ$ on the stratification length and none on the wall distance — to the present $ℓ = \min(ℂˢ z, \sqrt{e} / N)$, returning the equivalent LocalMinimumMixingLength and ConstantStabilityFunctions. The two lengths differ by the factor $Cᴺ$ everywhere, so the diffusivities and the dissipation rate are unchanged when $ℂˢ = 1 / Cᴺ$, the diffusivity coefficients are multiplied by $Cᴺ$ and the dissipation coefficient is divided by it.

using Breezeusing Breeze.TurbulenceClosures: absorb_stratification_coefficientmixing_length, stability_functions =    absorb_stratification_coefficient(0.76, ConstantStabilityFunctions(ℂᵘ=0.196, ℂᶜ=0.265, ℂᵉ=0.392, ℂᴰ=0.295))mixing_length# outputLocalMinimumMixingLength{Float64} (ℂˢ = 1.31579)
source
Breeze.TurbulenceClosures.buoyancy_penetration_depthᶜᶜᶠ — Method
buoyancy_penetration_depthᶜᶜᶠ(i, j, k, grid, closure, e, N²)

The buoyancy penetration depth $ℓᵇ = \sqrt{e} / N$ at (Center, Center, Face): how far an eddy with kinetic energy $e$ — floored at minimum_tke and reconstructed at the face from the cell centers — penetrates air of static stability $N²$ before its kinetic energy is spent against buoyancy. Infinite where $N² ≤ 0$, so that neutral and unstable air is no obstacle.

source
Breeze.TurbulenceClosures.dissipationᶜᶜᶜ — Method
dissipationᶜᶜᶜ(
    i,
    j,
    k,
    grid,
    closure,
    e,
    velocities,
    closure_fields
)

The dissipation rate $ε = Sᴰ e^{3/2} / ℓ$ at cell centers, from the specific turbulent kinetic energy field e, the velocities and the closure fields, whose stored $ℓ$ and $N²$ it reads; a diagnostic, evaluated in a KernelFunctionOperation at (Center, Center, Center) to compare the closure's TKE budget with a large-eddy simulation's. Negative $e$ dissipates nothing.

source
Breeze.TurbulenceClosures.mixing_lengthᶜᶜᶜ — Method
mixing_lengthᶜᶜᶜ(i, j, k, grid, closure, e, closure_fields)

The mixing length at cell center (i, j, k), where the dissipation lives with $e$. For the local minimum it is the local minimum at the center, with $N²$ reconstructed from the two adjacent faces. For the gradient-limited formulation, the uncapped stratification envelope is carried half a cell at slope $ℂⁱ$, then bounded by the center's local penetration depth and wall length $ℂˢ z$. The integral formulation carries its stored face length at slope $ℂˢ$.

source
Breeze.TurbulenceClosures.tke_sink_rate — Method
tke_sink_rate(
    i,
    j,
    k,
    grid,
    closure,
    e,
    B,
    velocities,
    closure_fields
)

The rate at which the sinks of the TKE equation remove turbulent kinetic energy, $-Lᵉ ≥ 0$: the dissipation rate $ω = Sᴰ \sqrt{e} / ℓ$ — or, where $e$ is negative, the damping rate $1/τ$ — plus the buoyancy sink rate $ωᴮ = -B⁻ / \max(e, eᵐⁱⁿ)$, the negative part of the buoyancy flux divided by $e$ floored at minimum_tke $eᵐⁱⁿ$. Above the floor the buoyancy sink $ωᴮ e$ is $-B⁻$; below it the sink falls linearly with $e$, continuously at $e = eᵐⁱⁿ$. Following CATKE, these are the terms treated implicitly in $e$, so that $e$ stays positive for any time step.

source

Utils

VerticalGrids

BreezeRRTMGPExt

Breeze.AtmosphereModels.RadiativeTransferModel — Method
RadiativeTransferModel(
    grid::Oceananigans.Grids.AbstractGrid,
    ::AllSkyOptics,
    constants::ThermodynamicConstants;
    liquid_effective_radius=ConstantRadiusParticles(1.0e-5),
    ice_effective_radius=ConstantRadiusParticles(3.0e-5),
    ice_roughness=2,
    keywords...
)

Construct an all-sky (gas + cloud) full-spectrum RadiativeTransferModel for the given grid.

This constructor requires that NCDatasets is loadable in the user environment because RRTMGP loads lookup tables from netCDF via an extension.

Keyword Arguments

  • background_atmosphere: Background atmospheric gas composition (default: BackgroundAtmosphere()). O₃ can be a Number, Function, or Field; other gases are global mean constants.
  • surface_temperature: Surface temperature in Kelvin, a Number or 2D Field. Default: nothing — bind one before the first radiation update (a coupled model wires its interface surface temperature into the radiation automatically).
  • solar_position: Specification of the solar zenith angle. See AbstractSolarPosition and its subtypes:
  • surface_emissivity: Surface emissivity, 0-1 (default: 0.98). Can be scalar or 2D field.
  • surface_albedo: Surface albedo, 0-1. Can be scalar or 2D field. Alternatively, provide both direct_surface_albedo and diffuse_surface_albedo.
  • direct_surface_albedo: Direct surface albedo, 0-1. Can be scalar or 2D field.
  • diffuse_surface_albedo: Diffuse surface albedo, 0-1. Can be scalar or 2D field.
  • solar_constant: Top-of-atmosphere solar flux in W/m² (default: 1361), a scalar or an (Nx, Ny) array of per-column values
  • column_batches: Number of batches to split the radiation solve into, trading speed for memory (default: nothing, one unbatched solve). The solver workspace, RRTMGP's dominant allocation, is then sized for one batch, so it shrinks by about that factor. Batches are whole j-rows of cld(Ny, column_batches) rows each, so the domain may need fewer batches than requested; when the rows do not divide Ny, the final batch overlaps the one before it. On GPUs the solver runs one thread per column, so batches of more than ~10⁵ columns cost nothing extra, while smaller batches take about as long as a full solve each.
  • liquid_effective_radius: Model for cloud liquid effective radius in meters (default: ConstantRadiusParticles(10e-6))
  • ice_effective_radius: Model for cloud ice effective radius in meters (default: ConstantRadiusParticles(30e-6))
  • ice_roughness: Ice crystal roughness for cloud optics (1=smooth, 2=medium, 3=rough; default: 2)
source
Breeze.AtmosphereModels.RadiativeTransferModel — Method
RadiativeTransferModel(
    grid::Oceananigans.Grids.AbstractGrid,
    ::ClearSkyOptics,
    constants::ThermodynamicConstants;
    keywords...
)

Construct a clear-sky (gas-only) full-spectrum RadiativeTransferModel for the given grid.

This constructor requires that NCDatasets is loadable in the user environment because RRTMGP loads lookup tables from netCDF via an extension.

Keyword Arguments

  • background_atmosphere: Background atmospheric gas composition (default: BackgroundAtmosphere()). O₃ can be a Number, Function, or Field; other gases are global mean constants.
  • surface_temperature: Surface temperature in Kelvin, a Number or 2D Field. Default: nothing — bind one before the first radiation update (a coupled model wires its interface surface temperature into the radiation automatically).
  • solar_position: Specification of the solar zenith angle. See AbstractSolarPosition and its subtypes:
  • surface_emissivity: Surface emissivity, 0-1 (default: 0.98). Can be scalar or 2D field.
  • surface_albedo: Surface albedo, 0-1. Can be scalar or 2D field. Alternatively, provide both direct_surface_albedo and diffuse_surface_albedo.
  • direct_surface_albedo: Direct surface albedo, 0-1. Can be scalar or 2D field.
  • diffuse_surface_albedo: Diffuse surface albedo, 0-1. Can be scalar or 2D field.
  • solar_constant: Top-of-atmosphere solar flux in W/m² (default: 1361), a scalar or an (Nx, Ny) array of per-column values
  • column_batches: Number of batches to split the radiation solve into, trading speed for memory (default: nothing, one unbatched solve). The solver workspace, RRTMGP's dominant allocation, is then sized for one batch, so it shrinks by about that factor. Batches are whole j-rows of cld(Ny, column_batches) rows each, so the domain may need fewer batches than requested; when the rows do not divide Ny, the final batch overlaps the one before it. On GPUs the solver runs one thread per column, so batches of more than ~10⁵ columns cost nothing extra, while smaller batches take about as long as a full solve each.
source
Breeze.AtmosphereModels.RadiativeTransferModel — Method
RadiativeTransferModel(
    grid::Oceananigans.Grids.AbstractGrid,
    ::GrayOptics,
    constants::ThermodynamicConstants;
    optical_thickness=GrayOpticalThicknessOGorman2008(eltype(grid)),
    surface_temperature=nothing,
    solar_position::AbstractSolarPosition=ApparentSolarPosition(),
    surface_emissivity=0.98,
    direct_surface_albedo=nothing,
    diffuse_surface_albedo=nothing,
    surface_albedo=nothing,
    solar_constant=1361,
    schedule=IterationInterval(1)
)

Construct a gray atmosphere radiative transfer model for the given grid.

Keyword Arguments

  • optical_thickness: Optical thickness parameterization (default: GrayOpticalThicknessOGorman2008(FT)).
  • surface_temperature: Surface temperature in Kelvin, a Number or 2D Field. Default: nothing — bind one before the first radiation update (a coupled model wires its interface surface temperature into the radiation automatically).
  • solar_position: Specification of the solar zenith angle. See AbstractSolarPosition and its subtypes:
  • surface_emissivity: Surface emissivity, 0-1 (default: 0.98). Can be scalar or 2D field.
  • surface_albedo: Surface albedo, 0-1. Can be scalar or 2D field. Alternatively, provide both direct_surface_albedo and diffuse_surface_albedo.
  • direct_surface_albedo: Direct surface albedo, 0-1. Can be scalar or 2D field.
  • diffuse_surface_albedo: Diffuse surface albedo, 0-1. Can be scalar or 2D field.
  • solar_constant: Top-of-atmosphere solar flux in W/m² (default: 1361), a scalar or an (Nx, Ny) array of per-column values
source
Breeze.AtmosphereModels._update_radiation! — Method
_update_radiation!(
    rtm::RadiativeTransferModel{<:Any, <:Any, <:Any, Nothing},
    model
)

Update the radiative fluxes from the current model state.

This function:

  1. Updates the RRTMGP atmospheric state from model fields (T, p)
  2. Computes the solar zenith angle from the model clock and grid location
  3. Solves the longwave and shortwave RTE
  4. Copies the fluxes to Oceananigans fields for output

Sign convention: positive flux = upward, negative flux = downward.

source
BreezeRRTMGPExt.full_spectrum_radiative_transfer_model — Method
full_spectrum_radiative_transfer_model(
    grid,
    radiation_method,
    constants,
    cloud_state,
    liquid_effective_radius,
    ice_effective_radius;
    background_atmosphere=BackgroundAtmosphere(),
    surface_temperature=nothing,
    solar_position::AbstractSolarPosition=ApparentSolarPosition(),
    surface_emissivity=0.98,
    direct_surface_albedo=nothing,
    diffuse_surface_albedo=nothing,
    surface_albedo=nothing,
    solar_constant=1361,
    schedule=IterationInterval(1),
    column_batches=nothing
)

Build a full-spectrum RadiativeTransferModel that solves with radiation_method. Clear-sky passes nothing for cloud_state and the effective radii; all-sky passes a CloudState and the effective radius models. The keyword arguments are those documented for the clear-sky and all-sky RadiativeTransferModel constructors.

source
BreezeRRTMGPExt.materialize_surface_radiation — Method
materialize_surface_radiation(
    grid,
    solar_position;
    surface_temperature,
    surface_emissivity,
    surface_albedo,
    direct_surface_albedo,
    diffuse_surface_albedo
)

Validate and materialize the user's surface properties into a SurfaceRadiation.

Albedo is given either as surface_albedo, used for both the direct and diffuse albedo, or as both direct_surface_albedo and diffuse_surface_albedo. Scalar emissivity, albedos and surface temperature become ConstantFields of the grid's float type; surface_temperature = nothing stays nothing until a coupled model binds one.

source
BreezeRRTMGPExt.rrtmgp_grid_params — Method
rrtmgp_grid_params(
    FT,
    context,
    grid,
    column_batches
) -> RRTMGP.RRTMGPGridParams{FT, <:ClimaComms.AbstractCommsContext} where FT

RRTMGP grid parameters for grid with ncol set to the width of one batch of columns. These size the solver workspace, which every batch shares; the state arrays stay sized for the whole domain.

source
BreezeRRTMGPExt.solve_radiation_batches! — Method
solve_radiation_batches!(rtm, solver, grid)

Solve longwave and shortwave over each batch of columns in turn and copy the fluxes into the Oceananigans fields.

Every batch must span the full workspace width: the solver's TransposedStateCache is refreshed with permutedims!, which throws DimensionMismatch on a narrower batch. So when the batch rows do not divide Ny, the final batch is shifted back to end at row Ny, re-solving rows the previous batch already covered.

source
BreezeRRTMGPExt.update_rrtmgp_state! — Method
update_rrtmgp_state!(
    rrtmgp_state::RRTMGP.AtmosphericStates.GrayAtmosphericState,
    model,
    surface_temperature
)

Update the RRTMGP GrayAtmosphericState arrays from model fields.

Grid staggering: layers vs levels

RRTMGP requires atmospheric state at both "layers" (cell centers) and "levels" (cell faces). This matches the finite-volume staggering used in Oceananigans:

                        ┌─────────────────────────────────────────────────┐    z_lev[Nz+1] ━━━━━━━ │  level Nz+1 (TOA):  p_lev, t_lev, z_lev         │ ← from halo                        └─────────────────────────────────────────────────┘                        ┌─────────────────────────────────────────────────┐                        │  layer Nz:  T[Nz], p_lay[Nz] = p[Nz]            │ ← from model                        └─────────────────────────────────────────────────┘    z_lev[Nz]   ━━━━━━━   level Nz:   p_lev, t_lev, z_lev                   ← interpolated                        ┌─────────────────────────────────────────────────┐                        │  layer Nz-1                                     │                        └─────────────────────────────────────────────────┘                                            ⋮                        ┌─────────────────────────────────────────────────┐                        │  layer 2                                        │                        └─────────────────────────────────────────────────┘    z_lev[2]    ━━━━━━━   level 2:    p_lev, t_lev, z_lev                   ← interpolated                        ┌─────────────────────────────────────────────────┐                        │  layer 1:   T[1], p_lay[1] = p[1]               │ ← from model                        └─────────────────────────────────────────────────┘    z_lev[1]    ━━━━━━━   level 1 (surface, bottom face):  p_lev, t_lev   │ ← from halo                        ══════════════════════════════════════════════════                                        GROUND (t_sfc)

Why the model must provide level values

RRTMGP is a general-purpose radiative transfer solver that operates on columns of atmospheric data. It does not interpolate from layers to levels internally because:

  1. Boundary conditions: The surface (level 1) and TOA (level Nz+1) require boundary values that only the atmospheric model knows. Breeze applies the same interior average there, so each boundary level takes whatever that field's halo carries. A Value bottom boundary condition (carried by the anelastic and 1D-column Exner reference pressures) reproduces the prescribed surface pressure exactly; a default NoFlux halo mirrors the interior (p[0] = p[1]), which collapses the level value onto the adjacent layer value.

    That prescribed value is surface_pressure, the pressure at the column's bottom face, and not the base_pressure datum at z = 0. The two coincide only on a domain whose bottom is the ground; on a raised or terrain-following domain they differ by the hydrostatic reduction from the datum to that face, which is the level 1 pressure radiation must see.

    TODO: extrapolate to the boundary faces explicitly rather than inheriting the halo. Wherever the halo mirrors, p_lev equals p_lay at that end, so the layer spans only half a cell in pressure while _compute_radiation_flux_divergence! still divides its flux difference by the full Δzᶜᶜᶜ, roughly halving that cell's heating rate. This affects the top cell always, and the bottom cell whenever dynamics_pressure carries no Value bottom boundary condition (compressible dynamics, and every terrain reference state).

  2. Interpolation to levels: Interior levels use ℑzᵃᵃᶠ, the arithmetic average of the two adjacent cell centers, for both pressure and temperature. That is second-order on a uniform column and first-order wherever Δz varies (stretched or terrain-following grids), since the face is then not the midpoint of its neighbouring centers.

  3. Model consistency: The pressure profile must be consistent with the atmospheric model's thermodynamic state. RRTMGP has no knowledge of the anelastic approximation or of which dynamical pressure contributions affect thermodynamics.

Physics notes

Temperature: We use the actual temperature field T from the model state. This is the temperature that matters for thermal emission and absorption.

Pressure: We use dynamics_pressure(model.dynamics) at cell centers — the anelastic hydrostatic reference pressure (in that approximation pressure perturbations are negligible), or the compressible diagnosed pressure. Never the dynamics' pressure-gradient reference state.

RRTMGP array layout

  • Layer arrays (Nz, Nc): values at cell centers, layer 1 at bottom
  • Level arrays (Nz+1, Nc): values at cell faces, level 1 at the surface (the bottom face)
source
BreezeRRTMGPExt.update_rrtmgp_surface_boundary_conditions! — Method
update_rrtmgp_surface_boundary_conditions!(
    ε₀,
    αᵈ₀,
    αˢ₀,
    surface_radiation,
    grid
)

Copy the surface emissivity ε and the direct and diffuse albedos αᵈ, αˢ from surface_radiation into RRTMGP's band-by-column boundary-condition arrays ε₀, αᵈ₀, αˢ₀.

Nothing else writes those arrays, so a spatially varying emissivity or albedo would otherwise never reach the solver, which would read whatever the allocation happened to contain. Call once at construction and again before every solve, so a property that evolves is picked up rather than frozen.

Breeze treats all three properties as spectrally grey: every band receives the same value.

source

BreezeCloudMicrophysicsExt

BreezeCloudMicrophysicsExt.AerosolActivation — Type
AerosolActivation{AP, AD, FT}

Aerosol activation parameters for two-moment microphysics.

Aerosol activation is the physical process that creates cloud droplets from aerosol particles when air becomes supersaturated. This struct bundles the parameters needed to compute the activation source term for cloud droplet number concentration.

Fields

  • activation: AerosolActivationParameters from CloudMicrophysics.jl
  • aerosol_distribution: Aerosol size distribution (modes with number, size, hygroscopicity)
  • nucleation_timescale: Nucleation timescale [s] for converting activation deficit to rate (default: 1s)

References

  • Abdul-Razzak, H. and Ghan, S.J. (2000). A parameterization of aerosol activation: 2. Multiple aerosol types. J. Geophys. Res., 105(D5), 6837-6844.
source
BreezeCloudMicrophysicsExt.MixedPhaseOneMomentState — Type
MixedPhaseOneMomentState{FT} <: AbstractMicrophysicalState{FT}

Microphysical state for mixed-phase one-moment bulk microphysics.

Contains the local mixing ratios for cloud liquid, cloud ice, rain, and snow. This state is used for both saturation adjustment and non-equilibrium cloud formation in mixed-phase simulations.

Fields

  • qᶜˡ: Cloud liquid mixing ratio (kg/kg)
  • qᶜⁱ: Cloud ice mixing ratio (kg/kg)
  • qʳ: Rain mixing ratio (kg/kg)
  • qˢⁿ: Snow mixing ratio (kg/kg)
  • w: Vertical velocity (m/s), used by the rain autoconversion
source
BreezeCloudMicrophysicsExt.OneMomentCloudMicrophysics — Type
OneMomentCloudMicrophysics(
    FT::DataType=Oceananigans.defaults.FloatType;
    cloud_formation=NonEquilibriumCloudFormation(nothing, nothing),
    categories=one_moment_cloud_microphysics_categories(FT),
    precipitation_boundary_condition=nothing,
    negative_moisture_correction=nothing
)

Return a OneMomentCloudMicrophysics microphysics scheme for warm-rain and mixed-phase precipitation.

The one-moment scheme uses CloudMicrophysics.jl 1M processes:

  • Condensation/evaporation of cloud liquid (relaxation toward saturation)
  • Autoconversion of cloud liquid to rain
  • Accretion of cloud liquid by rain
  • Terminal velocity for rain sedimentation

By default, non-equilibrium cloud formation is used, where cloud liquid is a prognostic variable that evolves via condensation/evaporation tendencies following Morrison and Grabowski (2008) (see Appendix A). The prognostic variables are ρqᶜˡ (cloud liquid mass density) and ρqʳ (rain mass density).

For equilibrium (saturation adjustment) cloud formation, pass:

using Breeze.Microphysicscloud_formation = SaturationAdjustment(equilibrium=WarmPhaseEquilibrium())# outputSaturationAdjustment{WarmPhaseEquilibrium, Breeze.Solvers.SecantSolver{Float64}}(WarmPhaseEquilibrium(), SecantSolver(reltol=0.0, abstol=0.0001, maxiter=20))

Keyword arguments

  • categories: One-moment parameters and terminal velocities, typically built with one_moment_cloud_microphysics_categories.
  • precipitation_boundary_condition: Controls whether precipitation passes through the bottom boundary.
    • nothing (default): Rain exits through the bottom (open boundary)
    • ImpenetrableBoundaryCondition(): Rain collects at the bottom (zero terminal velocity at surface)

See the CloudMicrophysics.jl documentation for details.

References

  • Morrison, H. and Grabowski, W. W. (2008). A novel approach for representing ice microphysics in models: Description and tests using a kinematic framework. J. Atmos. Sci., 65, 1528–1548. https://doi.org/10.1175/2007JAS2491.1
source
BreezeCloudMicrophysicsExt.TwoMomentCategories — Type
TwoMomentCategories{W, AP, LV, RV, AA, TL}

Parameters for two-moment (Seifert and Beheng, 2006) warm-rain microphysics.

Fields

  • warm_processes: Seifert and Beheng (2006) parameters bundling autoconversion, accretion, self-collection, breakup, evaporation, number adjustment, and size distribution parameters
  • air: AirProperties for thermodynamic calculations
  • cloud_liquid_fall_velocity: StokesRegimeVelType for cloud droplet terminal velocity
  • rain_fall_velocity: SB2006VelType or Chen2022VelTypeRain for raindrop terminal velocity
  • aerosol_activation: AerosolActivation parameters for cloud droplet nucleation (or nothing to disable)
  • τⁿᵘᵐ: Timescale [s] for per-reservoir tendency limiting (default: 10)

References

  • Abdul-Razzak, H. and Ghan, S.J. (2000). A parameterization of aerosol activation: 2. Multiple aerosol types. J. Geophys. Res., 105(D5), 6837-6844.
  • Seifert, A. and Beheng, K. D. (2006). A two-moment cloud microphysics parameterization for mixed-phase clouds. Part 1: Model description. Meteorol. Atmos. Phys., 92, 45-66. https://doi.org/10.1007/s00703-005-0112-4
source
BreezeCloudMicrophysicsExt.TwoMomentCloudMicrophysics — Type
TwoMomentCloudMicrophysics(
    FT::DataType=Oceananigans.defaults.FloatType;
    cloud_formation=NonEquilibriumCloudFormation(nothing, nothing),
    categories=two_moment_cloud_microphysics_categories(FT),
    precipitation_boundary_condition=nothing,
    negative_moisture_correction=nothing
)

Return a TwoMomentCloudMicrophysics microphysics scheme for warm-rain precipitation using the Seifert and Beheng (2006) two-moment parameterization.

The two-moment scheme tracks both mass and number concentration for cloud liquid and rain, using CloudMicrophysics.jl 2M processes:

  • Aerosol activation: Creates cloud droplets when supersaturation develops (enabled by default)
  • Condensation/evaporation of cloud liquid (relaxation toward saturation)
  • Autoconversion of cloud liquid to rain (mass and number)
  • Accretion of cloud liquid by rain (mass and number)
  • Cloud liquid self-collection (number only)
  • Rain self-collection and breakup (number only)
  • Rain evaporation (mass and number)
  • Number adjustment to maintain physical mean particle mass bounds
  • Terminal velocities (number-weighted and mass-weighted)

Non-equilibrium cloud formation is used, where cloud liquid mass and number are prognostic variables that evolve via condensation/evaporation, aerosol activation, and microphysical tendencies.

The prognostic variables are:

  • ρqᶜˡ: cloud liquid mass density [kg/m³]
  • ρnᶜˡ: cloud liquid number density [1/m³]
  • ρqʳ: rain mass density [kg/m³]
  • ρnʳ: rain number density [1/m³]

Aerosol Activation

Aerosol activation is enabled by default and provides the physical source term for cloud droplet number concentration. Without activation, cloud droplets cannot form. The default aerosol population represents typical continental conditions (~100 cm⁻³).

To customize the aerosol population, pass a custom categories with different aerosol_activation:

# Marine aerosol (fewer, more hygroscopic particles)marine_mode = CMAM.Mode_κ(0.08e-6, 1.8, 50e6, (1.0,), (1.0,), (0.058,), (1.0,))marine_activation = AerosolActivation(    AerosolActivationParameters(Float64),    CMAM.AerosolDistribution((marine_mode,)))categories = two_moment_cloud_microphysics_categories(aerosol_activation = marine_activation)microphysics = TwoMomentCloudMicrophysics(categories = categories)

Keyword arguments

  • cloud_formation: Cloud formation scheme (default: NonEquilibriumCloudFormation)
  • categories: TwoMomentCategories containing SB2006 and aerosol activation parameters
  • precipitation_boundary_condition: Controls whether precipitation passes through the bottom boundary.
    • nothing (default): Rain exits through the bottom (open boundary)
    • ImpenetrableBoundaryCondition(): Rain collects at the bottom (zero terminal velocity at surface)

See the CloudMicrophysics.jl 2M documentation for details on the Seifert and Beheng (2006) scheme.

References

  • Seifert, A. and Beheng, K. D. (2006). A two-moment cloud microphysics parameterization for mixed-phase clouds. Part 1: Model description. Meteorol. Atmos. Phys., 92, 45-66. https://doi.org/10.1007/s00703-005-0112-4
  • Abdul-Razzak, H. and Ghan, S.J. (2000). A parameterization of aerosol activation: 2. Multiple aerosol types. J. Geophys. Res., 105(D5), 6837-6844.
source
BreezeCloudMicrophysicsExt.WarmPhaseOneMomentState — Type
WarmPhaseOneMomentState{FT} <: AbstractMicrophysicalState{FT}

Microphysical state for warm-phase one-moment bulk microphysics.

Contains the local mixing ratios needed to compute tendencies for cloud liquid and rain. This state is used for both saturation adjustment and non-equilibrium cloud formation in warm-phase (liquid only) simulations.

Fields

  • qᶜˡ: Cloud liquid mixing ratio (kg/kg)
  • qʳ: Rain mixing ratio (kg/kg)
  • w: Vertical velocity (m/s), used by the rain autoconversion
source
BreezeCloudMicrophysicsExt.WarmPhaseTwoMomentState — Type
WarmPhaseTwoMomentState{FT, V} <: AbstractMicrophysicalState{FT}

Microphysical state for warm-phase two-moment bulk microphysics.

Contains the local mixing ratios and number concentrations needed to compute tendencies for cloud liquid and rain following the Seifert-Beheng 2006 scheme.

Fields

  • qᶜˡ: Cloud liquid mixing ratio (kg/kg)
  • nᶜˡ: Cloud liquid number per unit mass (1/kg)
  • qʳ: Rain mixing ratio (kg/kg)
  • nʳ: Rain number per unit mass (1/kg)
  • nᵃ: Aerosol number per unit mass (1/kg)
  • velocities: NamedTuple of velocity components (; u, v, w) [m/s]. The vertical velocity w is used for aerosol activation.

References

  • Seifert, A. and Beheng, K. D. (2006). A two-moment cloud microphysics parameterization for mixed-phase clouds. Part 1: Model description. Meteorol. Atmos. Phys., 92, 45-66. https://doi.org/10.1007/s00703-005-0112-4
source
BreezeCloudMicrophysicsExt.aerosol_activation_mass_tendency — Method
aerosol_activation_mass_tendency(
    aerosol_activation::BreezeCloudMicrophysicsExt.AerosolActivation,
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    ρ::FT,
    ℳ::BreezeCloudMicrophysicsExt.WarmPhaseTwoMomentState{FT},
    𝒰,
    constants
) where FT

Compute the cloud liquid mass tendency from aerosol activation.

When aerosol particles activate to form cloud droplets, the newly formed droplets have a finite initial size given by the activation radius. This function computes the corresponding mass source term for cloud liquid water.

The activation radius is derived from Köhler theory:

\[r_{act} = \frac{2A}{3 𝒮}\]

where $A = 2σ/(ρ_w R_v T)$ is the curvature parameter and $𝒮$ is the instantaneous supersaturation. See eq. 19 in Abdul-Razzak et al. (1998).

The mass tendency is then:

\[\frac{\mathrm{d}q^{cl}}{\mathrm{d}t}_{act} = \frac{\mathrm{d}N^{cl}}{\mathrm{d}t}_{act} \frac{4}{3} π r_{act}^3 \frac{ρ_w}{ρ}\]

The activation rate is controlled by the nucleation timescale τⁿᵘᶜ stored in the AerosolActivation parameters (default: 1s).

Returns

Mass tendency for cloud liquid [kg/kg/s]

source
BreezeCloudMicrophysicsExt.cloud_ice_melting — Method
cloud_ice_melting(
    cloud_ice::CloudMicrophysics.Parameters.CloudIce,
    air::CloudMicrophysics.Parameters.AirProperties,
    qᶜⁱ::FT,
    ρ::FT,
    T::FT,
    Tᶠ::FT,
    constants
) where FT

Compute melting of cloud ice to cloud liquid using Breeze thermodynamics.

source
BreezeCloudMicrophysicsExt.default_aerosol_activation — Function
default_aerosol_activation(
    FT::DataType=Float64;
    τⁿᵘᶜ=1
) -> BreezeCloudMicrophysicsExt.AerosolActivation{AP, AD} where {AP<:CloudMicrophysics.Parameters.AerosolActivationParameters, AD<:(CloudMicrophysics.AerosolModel.AerosolDistribution{T} where T<:Tuple{CloudMicrophysics.AerosolModel.Mode_κ{T} where T<:Tuple{Any}})}

Create a default AerosolActivation representing a typical continental aerosol population.

The default distribution is a single mode with:

  • Mean dry radius: 0.05 μm (50 nm)
  • Geometric standard deviation: 2.0
  • Number concentration: 100 cm⁻³ (100 × 10⁶ m⁻³)
  • Hygroscopicity κ: 0.5 (typical for ammonium sulfate)

Keyword arguments

  • τⁿᵘᶜ: Nucleation timescale [s] for converting activation deficit to rate (default: 1s). Controls how quickly the cloud droplet number relaxes toward the target activated number.

This provides sensible out-of-the-box behavior for two-moment microphysics. Users can customize the aerosol population by constructing their own AerosolActivation.

Example

# Use default aerosolmicrophysics = TwoMomentCloudMicrophysics()# Custom aerosol: marine (fewer, larger particles)marine_mode = CMAM.Mode_κ(0.08e-6, 1.8, 50e6, (1.0,), (1.0,), (0.058,), (1.0,))marine_aerosol = AerosolActivation(    AerosolActivationParameters(Float64),    CMAM.AerosolDistribution((marine_mode,)),    1  # τⁿᵘᶜ = 1s)microphysics = TwoMomentCloudMicrophysics(aerosol_activation = marine_aerosol)# Disable aerosol activation (not recommended)microphysics = TwoMomentCloudMicrophysics(aerosol_activation = nothing)
source
BreezeCloudMicrophysicsExt.diffusional_growth_factor — Method
diffusional_growth_factor(
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    T,
    constants
) where FT

Compute the thermodynamic factor $G$ that controls the rate of diffusional growth of cloud droplets and rain drops.

The $G$ factor combines the effects of thermal conductivity and vapor diffusivity on phase change. It appears in the Mason equation for droplet growth:

\[\frac{\mathrm{d}m}{\mathrm{d}t} = 4π r G 𝒮\]

where $𝒮$ is supersaturation and $r$ is droplet radius.

This is a translation of CloudMicrophysics.Common.G_func_liquid using Breeze's thermodynamics instead of Thermodynamics.jl.

See Eq. (13.28) by Pruppacher & Klett (2010).

References

  • Pruppacher, H. R., Klett, J. D. (2010). Microphysics of clouds and precipitation. Springer Netherlands. 2nd Edition
source
BreezeCloudMicrophysicsExt.ice_autoconversion_with_supersaturation — Method
ice_autoconversion_with_supersaturation(
    option::CloudMicrophysics.Parameters.WithSupersaturation,
    parameters::CloudMicrophysics.Parameters.Microphysics1MParams,
    q::Breeze.Thermodynamics.MoistureMassFractions{FT},
    qᶜⁱ::FT,
    ρ::FT,
    ρᵗʰ::FT,
    T::FT,
    Tᶠ::FT,
    constants
) where FT

Compute supersaturation-dependent autoconversion of cloud ice to snow using Breeze thermodynamics.

The supersaturation is evaluated at the thermodynamic state density ρᵗʰ; the size distribution uses the total density ρ, which weights the prognostic condensate.

source
BreezeCloudMicrophysicsExt.max_supersaturation_breeze — Method
max_supersaturation_breeze(
    aerosol_activation::BreezeCloudMicrophysicsExt.AerosolActivation,
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    ρ::FT,
    ℳ::BreezeCloudMicrophysicsExt.WarmPhaseTwoMomentState{FT},
    𝒰,
    constants
) where FT

Compute the maximum supersaturation using the Abdul-Razzak and Ghan (2000) parameterization.

This is a translation of CloudMicrophysics.AerosolActivation.max_supersaturation that uses Breeze's thermodynamics instead of Thermodynamics.jl.

Arguments

  • aerosol_activation: AerosolActivation containing activation parameters and aerosol distribution
  • aps: AirProperties (thermal conductivity, vapor diffusivity)
  • ρ: Air density [kg/m³]
  • ℳ: Microphysical state containing updraft velocity and number concentrations
  • 𝒰: Thermodynamic state
  • constants: Breeze ThermodynamicConstants

Returns

Maximum supersaturation (dimensionless, e.g., 0.01 = 1% supersaturation)

References

  • Abdul-Razzak, H. and Ghan, S.J. (2000). A parameterization of aerosol activation: 2. Multiple aerosol types. J. Geophys. Res., 105(D5), 6837-6844.
source
BreezeCloudMicrophysicsExt.one_moment_cloud_microphysics_categories — Function
one_moment_cloud_microphysics_categories(
    FT::DataType=Oceananigans.defaults.FloatType;
    parameters=Microphysics1MParams(FT),
    hydrometeor_velocities=TerminalVelocityParams(FT),
    freezing_temperature=FT(273.15),
    τⁿᵘᵐ=FT(10)
)

Return one-moment categories backed by CloudMicrophysics' unified Microphysics1MParams container.

Keyword arguments

  • parameters: CloudMicrophysics particle parameters and process options.
  • hydrometeor_velocities: Terminal-velocity parameters for cloud condensate. Its rain and snow component is replaced with parameters.terminal_velocity so the two containers cannot diverge.
  • freezing_temperature: Temperature used to route melting and freezing processes. Defaults to CloudMicrophysics' standard value, 273.15 K.
  • τⁿᵘᵐ: Timescale [s] for limiting sinks and relaxing negative values: a donor reservoir loses at most its content over τⁿᵘᵐ. Must satisfy τⁿᵘᵐ ≥ Δt to prevent reservoir overdraw within one time step. Default: 10 seconds.
source
BreezeCloudMicrophysicsExt.rain_evaporation — Method
rain_evaporation(
    (; pdf, mass, vent)::CloudMicrophysics.Parameters.Rain,
    vel::CloudMicrophysics.Parameters.Blk1MVelTypeRain{FT},
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    q::Breeze.Thermodynamics.MoistureMassFractions{FT},
    qʳ::FT,
    ρ::FT,
    ρᵗʰ::FT,
    T::FT,
    constants
) where FT

Compute the rain evaporation rate (dqʳ/dt, negative for evaporation).

This is a translation of CloudMicrophysics.Microphysics1M.conv_q_rai_to_q_vap that uses Breeze's internal thermodynamics instead of Thermodynamics.jl.

Arguments

  • rain_params: Rain microphysics parameters (pdf, mass, vent)
  • vel: Terminal velocity parameters
  • aps: Air properties (kinematic viscosity, vapor diffusivity, thermal conductivity)
  • q: MoistureMassFractions containing vapor, liquid, and ice mass fractions
  • qʳ: Rain specific humidity
  • ρ: Total density, which weights the prognostic rain $ρqʳ$; used for the size distribution. On the anelastic core this is the reference density $ρᵣ$.
  • ρᵗʰ: Thermodynamic state density, density(𝒰, constants); used for the supersaturation. On the compressible core $ρᵗʰ = ρ$.
  • T: Temperature
  • constants: Breeze ThermodynamicConstants

Returns

Rate of change of rain specific humidity (negative = evaporation)

source
BreezeCloudMicrophysicsExt.rain_evaporation_2m — Method
rain_evaporation_2m(
    (; pdf_r, evap)::CloudMicrophysics.Parameters.SB2006,
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    q::Breeze.Thermodynamics.MoistureMassFractions{FT},
    qʳ::FT,
    ρ::FT,
    ρᵗʰ::FT,
    Nʳ::FT,
    T::FT,
    constants
) where FT -> NamedTuple{(:evap_rate_0, :evap_rate_1), <:Tuple{Any, Any}}

Compute the two-moment rain evaporation rate returning both number and mass tendencies.

This is a translation of CloudMicrophysics.Microphysics2M.rain_evaporation that uses Breeze's internal thermodynamics instead of Thermodynamics.jl.

Arguments

  • sb: SB2006 parameters containing pdf_r and evap
  • aps: Air properties (kinematic viscosity, vapor diffusivity, thermal conductivity)
  • q: MoistureMassFractions containing vapor, liquid, and ice mass fractions
  • qʳ: Rain specific humidity [kg/kg]
  • ρ: Total density, which weights the prognostic rain [kg/m³]; used for the size distribution
  • ρᵗʰ: Thermodynamic state density, density(𝒰, constants) [kg/m³]; used for the supersaturation
  • Nʳ: Rain number concentration [1/m³]
  • T: Temperature [K]
  • constants: Breeze ThermodynamicConstants

Returns

Named tuple (; evap_rate_0, evap_rate_1) where:

  • evap_rate_0: Rate of change of number concentration [m⁻³ s⁻¹)], negative for evaporation
  • evap_rate_1: Rate of change of mass mixing ratio [kg/kg/s], negative for evaporation
source
BreezeCloudMicrophysicsExt.snow_melting — Method
snow_melting(
    (; pdf, mass, vent)::CloudMicrophysics.Parameters.Snow{FT},
    vel::CloudMicrophysics.Parameters.Blk1MVelTypeSnow{FT},
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    qˢⁿ::FT,
    ρ::FT,
    T::FT,
    Tᶠ::FT,
    constants
) where FT

Compute the snow melting rate (dqˢⁿ/dt due to melting, always non-negative).

Sensible-heat-driven melting: heat from warm air ($T > Tᶠ$) melts snow to rain. The rate is proportional to ($T - Tᶠ$) and includes ventilation corrections.

This is a translation of CloudMicrophysics.Microphysics1M.conv_q_sno_to_q_rai that uses Breeze's internal thermodynamics instead of Thermodynamics.jl.

Arguments

  • snow_params: Snow microphysics parameters (pdf, mass, vent)
  • vel: Snow terminal velocity parameters
  • aps: Air properties (kinematic viscosity, vapor diffusivity, thermal conductivity)
  • qˢⁿ: Snow specific humidity
  • ρ: Air density
  • T: Temperature
  • Tᶠ: Freezing temperature
  • constants: Breeze ThermodynamicConstants

Returns

Rate of snow mass lost to melting [kg/kg/s] (always non-negative)

source
BreezeCloudMicrophysicsExt.snow_sublimation_deposition — Method
snow_sublimation_deposition(
    (; pdf, mass, vent)::CloudMicrophysics.Parameters.Snow{FT},
    vel::CloudMicrophysics.Parameters.Blk1MVelTypeSnow{FT},
    aps::CloudMicrophysics.Parameters.AirProperties{FT},
    q::Breeze.Thermodynamics.MoistureMassFractions{FT},
    qˢⁿ::FT,
    ρ::FT,
    ρᵗʰ::FT,
    T::FT,
    constants
) where FT

Compute the snow sublimation/deposition rate (dqˢⁿ/dt).

Positive values mean deposition (vapor → snow), negative means sublimation (snow → vapor). Unlike rain evaporation, both signs are physical for snow.

This is a translation of CloudMicrophysics.Microphysics1M.conv_q_sno_to_q_vap for snow that uses Breeze's internal thermodynamics instead of Thermodynamics.jl.

Arguments

  • snow_params: Snow microphysics parameters (pdf, mass, vent)
  • vel: Snow terminal velocity parameters
  • aps: Air properties (kinematic viscosity, vapor diffusivity, thermal conductivity)
  • q: MoistureMassFractions containing vapor, liquid, and ice mass fractions
  • qˢⁿ: Snow specific humidity
  • ρ: Total density, which weights the prognostic snow; used for the size distribution
  • ρᵗʰ: Thermodynamic state density, density(𝒰, constants); used for the supersaturation
  • T: Temperature
  • constants: Breeze ThermodynamicConstants

Returns

Rate of change of snow specific humidity (positive = deposition, negative = sublimation)

source
BreezeCloudMicrophysicsExt.temperature_dependent_ice_relaxation_timescale — Method
temperature_dependent_ice_relaxation_timescale(
    cloud_ice::CloudMicrophysics.Parameters.CloudIce,
    air::CloudMicrophysics.Parameters.AirProperties,
    frostenberg,
    qᶜⁱ,
    T
)

Return the cloud-ice deposition relaxation timescale for the CloudMicrophysics TemperatureDependent option.

This is a branch-free translation of CloudMicrophysics.MicrophysicsNonEq.τ_relax for use from Breeze GPU kernels.

source
BreezeCloudMicrophysicsExt.two_moment_cloud_microphysics_categories — Function
two_moment_cloud_microphysics_categories(
    FT::DataType=Oceananigans.defaults.FloatType;
    warm_processes=SB2006(FT),
    air=AirProperties(FT),
    cloud_liquid_fall_velocity=StokesRegimeVelType(FT),
    rain_fall_velocity=SB2006VelType(FT),
    aerosol_activation=default_aerosol_activation(FT),
    τⁿᵘᵐ=FT(10)
)

Construct TwoMomentCategories with default Seifert-Beheng 2006 parameters and aerosol activation.

Keyword arguments

  • warm_processes: Seifert-Beheng 2006 parameters for warm-rain microphysics
  • air: Air properties for thermodynamic calculations
  • cloud_liquid_fall_velocity: Terminal velocity parameters for cloud droplets (Stokes regime)
  • rain_fall_velocity: Terminal velocity parameters for rain drops
  • aerosol_activation: Aerosol activation parameters (default: continental aerosol). Set to nothing to disable activation (not recommended for physical simulations).
  • τⁿᵘᵐ: Timescale [s] for per-reservoir tendency limiting. Must satisfy τⁿᵘᵐ ≥ Δt to prevent reservoir overdraw. Default: 10 seconds.

References

  • Seifert, A. and Beheng, K. D. (2006). A two-moment cloud microphysics parameterization for mixed-phase clouds. Part 1: Model description. Meteorol. Atmos. Phys., 92, 45-66. https://doi.org/10.1007/s00703-005-0112-4
source
BreezeCloudMicrophysicsExt.warm_accretion_melt_factor — Method
warm_accretion_melt_factor(
    T::FT,
    Tᶠ::FT,
    constants
) where FT

Compute the thermal melt factor for warm accretion processes.

When cloud liquid or rain collides with snow above freezing, the sensible heat carried by the warm hydrometeor melts additional snow. The factor $α$ gives the mass ratio of melted snow to accreted warm hydrometeor mass:

\[α = cˡ (T - Tᶠ) / ℒ_f\]

This is a translation of CloudMicrophysics.Microphysics1M.warm_accretion_melt_factor that uses Breeze's internal thermodynamics instead of Thermodynamics.jl.

Arguments

  • T: Temperature
  • Tᶠ: Freezing temperature
  • constants: Breeze ThermodynamicConstants

Returns

Thermal melt factor α (zero when $T ≤ Tᶠ$)

source

BreezeNumericalRadiationExt

Breeze.AtmosphereModels.RadiativeTransferModel — Method
RadiativeTransferModel(
    grid::Oceananigans.Grids.AbstractGrid,
    optics::EcCKDOptics,
    constants::ThermodynamicConstants;
    background_atmosphere=BackgroundAtmosphere(),
    surface_temperature=nothing,
    solar_position::AbstractSolarPosition=ApparentSolarPosition(),
    surface_emissivity=0.98,
    surface_albedo=nothing,
    direct_surface_albedo=nothing,
    diffuse_surface_albedo=nothing,
    solar_constant=1361,
    schedule=IterationInterval(1),
    liquid_effective_radius=ConstantRadiusParticles(1.0e-5),
    ice_effective_radius=ConstantRadiusParticles(3.0e-5),
    overlying_atmosphere=OverlyingAtmosphereColumn(eltype(grid)),
    column_batches=nothing
)

Construct a full-spectrum RadiativeTransferModel on grid with the ecCKD gas optics of optics::EcCKDOptics, solved column by column by NumericalRadiation.jl. Radiation is solved on the grid's layers plus the layers of overlying_atmosphere above the grid top (a OverlyingAtmosphereColumn, or nothing to stop at the grid top).

With optics.clouds::CloudScatteringTables the radiation is all-sky: the cloud liquid and ice of every grid cell (from the model's microphysics) scatter and absorb with the scattering tables mapped onto the ecCKD g points at the constant effective radii of liquid_effective_radius and ice_effective_radius; the shortwave folds the cloud scattering into the two-stream solution and the longwave adds the cloud absorption κ (1 - ω) W only and neglects longwave cloud scattering (ecRad's do_lw_cloud_scattering = false setting, and what RRTMGP's no-scattering longwave solver does; scattering is a planned follow-up). With optics.clouds = nothing the sky is clear whatever the microphysics holds.

The gas optics and cloud scattering tables are read from netCDF files, which requires using NCDatasets. The column kernel takes gravity and the molar masses from constants; the Stefan–Boltzmann constant of the gray Planck source (used by g points without a source table) is carried by the gas optics model.

Keyword Arguments

  • background_atmosphere: Background atmospheric gas composition (default: BackgroundAtmosphere()). O₃ can be a Number or Function of z; CO₂, CH₄, N₂O, CFC₁₁ and CFC₁₂ are well-mixed. The remaining gases of BackgroundAtmosphere are not tabulated by the ecCKD models and must be zero.
  • surface_temperature: Surface temperature in Kelvin, a Number or 2D Field. Default: nothing — bind one before the first radiation update (a coupled model wires its interface surface temperature into the radiation automatically).
  • solar_position: Specification of the solar zenith angle. See AbstractSolarPosition and its subtypes:
  • surface_emissivity: Surface emissivity, 0-1 (default: 0.98). Can be scalar or 2D field.
  • surface_albedo: Surface albedo, 0-1. Can be scalar or 2D field. Alternatively, provide both direct_surface_albedo and diffuse_surface_albedo.
  • direct_surface_albedo: Direct surface albedo, 0-1. Can be scalar or 2D field.
  • diffuse_surface_albedo: Diffuse surface albedo, 0-1. Can be scalar or 2D field.
  • solar_constant: Top-of-atmosphere solar flux in W/m² (default: 1361), a scalar or an (Nx, Ny) array of per-column values
  • schedule: When to recompute the fluxes (default: IterationInterval(1), every iteration)
  • liquid_effective_radius: Model for cloud liquid effective radius in meters (default: ConstantRadiusParticles(10e-6)); only ConstantRadiusParticles for now
  • ice_effective_radius: Model for cloud ice effective radius in meters (default: ConstantRadiusParticles(30e-6)); only ConstantRadiusParticles for now
  • overlying_atmosphere: The atmosphere above the grid top (default: OverlyingAtmosphereColumn(eltype(grid)); nothing solves the grid's column only, with no atmosphere above it)
  • column_batches: Number of batches to split the radiation solve into, trading speed for memory (default: nothing, one unbatched solve). The per-column state and scratch are then stored for one batch only. Batches are whole j-rows of cld(Ny, column_batches) rows each, as for the RRTMGP optics; when the rows do not divide Ny, the final batch overlaps the one before it. Each batch is a separate kernel launch of a register-limited kernel, so on a GPU smaller batches cost time: keep batches to several times the number of columns the GPU solves at once.
source
BreezeNumericalRadiationExt.ColumnState — Type
struct ColumnState{G, P, T, D, M, MP, MF, O, X, XP, C}

The model fields, constants and overlying atmosphere from which layer_state and interface_temperature compute the state of the extended columns, and the batch of columns being solved: the extension pressures are those of the batch whose first row follows row_offset rows of the grid.

source
BreezeNumericalRadiationExt.ColumnState — Method
ColumnState(
    rtm,
    model,
    row_offset
) -> BreezeNumericalRadiationExt.ColumnState

The ColumnState of model with the ozone of rtm's background atmosphere and the extension and extension pressures of rtm's workspace, for the batch of columns that follows row_offset rows of the grid.

source
BreezeNumericalRadiationExt.ColumnWorkspace — Type
struct ColumnWorkspace{FT, AF, FF, S, W, P, V, X}

Per-layer state and solver scratch of the ecCKD radiation of one batch of Nb = Nx × rows columns of N layers.

Fields:

  • stencil: The gas optics stencil of every layer, a LayerStencils, or nothing for a gas optics model without interpolation tables
  • dry_air, water_vapor, ozone: Layer gas amounts [mol m⁻²], (Nb, N)
  • liquid_water_path, ice_water_path: Layer cloud water paths [kg m⁻²], (Nb, N), or nothing for a clear sky
  • interface_temperatures: Interface temperatures [K], (Nb, N + 1)
  • reflectance, transmittance, direct_reflectance, direct_diffuse_transmittance, direct_flux: Shortwave adding-method layer scratch, (Nb, N). The longwave solution reuses transmittance and reflectance for its layer transmittance and upward source.
  • stack_albedo, source: Shortwave adding-method interface scratch, (Nb, N + 1)
  • extension_pressure: Hydrostatic pressure on the extension faces, bottom-up from the grid top, (Nb, Nₑ + 1), or nothing without an overlying atmosphere
  • cos_zenith: Cosine of the solar zenith angle of every column of the grid, (Nx Ny,)
  • extension: The materialized OverlyingAtmosphereColumn above the grid top, or nothing
  • rows: The number of grid rows in a batch

Layer and interface arrays carry separate types: Reactant's kernel arrays encode their dimensions in the type, and interfaces have one more vertical entry.

source
BreezeNumericalRadiationExt.ColumnWorkspace — Method
ColumnWorkspace(
    arch,
    FT,
    Nx,
    rows,
    Nc,
    N,
    gas_model,
    cloud,
    extension
)

Allocate a zeroed ColumnWorkspace of float type FT on architecture arch for batches of rows rows of Nx columns of N layers, and the cosine of the solar zenith angle of all Nc columns of the grid. gas_model decides whether there are stencils to store, cloud whether there are water paths, and extension (a materialized OverlyingAtmosphereColumn or nothing) whether there are extension pressures.

source
BreezeNumericalRadiationExt.EcCKDLongwave — Type
struct EcCKDLongwave{M, C, W, FT}

The longwave half of an ecCKD radiation model.

Fields:

  • gas_model: ecCKD gas optics model
  • cloud: Longwave cloud optics, or nothing for clear sky
  • weights: Longwave spectral weights
  • mole_fractions: Mole fractions of the well-mixed gases relative to dry air
source
BreezeNumericalRadiationExt.EcCKDShortwave — Type
struct EcCKDShortwave{M, C, W, S}

The shortwave half of an ecCKD radiation model.

Fields:

  • gas_model: ecCKD gas optics model
  • cloud: Shortwave cloud optics, or nothing for clear sky
  • weights: Shortwave spectral weights
  • solar_constant: Solar constant [W m⁻²], a number or an (Nx, Ny) array of per-column values
source
BreezeNumericalRadiationExt.FaceFluxColumn — Type
struct FaceFluxColumn{FT, D} <: AbstractVector{FT}

The fluxes on column (i, j) of a ZFaceField presented to NumericalRadiation's solvers as a top-down vector of the N + 1 column interfaces, each stream positive in its own direction: column interface k is grid face N + 2 - k, sign converts between NumericalRadiation's convention and Breeze's positive-upward one, and the Nₑ interfaces above the grid top (whose fluxes only the solvers' sweeps need, and which they never read back) are not stored.

source
BreezeNumericalRadiationExt.LayerOptics — Type
struct LayerOptics{S, M, W, L, I, BL, BI, FT}

Layer optics of batch column c for NumericalRadiation's streaming solvers, read from the layer pass's per-layer state in workspace. The longwave functor returns (τ, Bₖ, Bₖ₊₁) at (g, k): the gas absorption optical depth of layer k at g point g plus the cloud absorption of both phases, and the Planck sources at the layer's top and bottom interfaces. The shortwave functor returns (τₐ, τₛ, 𝒢): the gas absorption optical depth, the Rayleigh scattering of the layer's air (the dry-air amount, which in the dry convention is the layer's total mass over mᵈ, as in NumericalRadiation's array path), and the scattering of both cloud phases folded in.

Fields:

  • gas_model: ecCKD gas optics model
  • workspace: The ColumnWorkspace
  • mole_fractions: Mole fractions of the well-mixed gases relative to dry air
  • liquid_cloud, ice_cloud: Cloud optics of each phase, or nothing
  • liquid_bracket, ice_bracket: Effective radius brackets of the cloud optics
  • column: The batch column
source
BreezeNumericalRadiationExt.LayerStencils — Type
struct LayerStencils{AI, AF}

The gas optics stencil of every layer of a batch: the lower index and weight of the pressure, temperature and water vapor brackets, (Nb, N) each. The upper index of every bracket is the lower index plus one.

source
BreezeNumericalRadiationExt.column_atmosphere — Method
column_atmosphere(
    rtm::RadiativeTransferModel{<:Any, <:Any, <:Any, <:BackgroundAtmosphere, <:BreezeNumericalRadiationExt.ColumnWorkspace},
    model,
    i,
    j
) -> NumericalRadiation.ColumnAtmosphere{<:Any, <:Any, <:Any, <:Any, <:Any, G, S, Geo, C} where {G<:(NamedTuple{(:dry_air, :H₂O, :O₃, :CO₂, :CH₄, :N₂O, :CFC₁₁, :CFC₁₂), <:NTuple{8, Any}}), S<:(NamedTuple{(:temperature, :emissivity), <:Tuple{Any, Any}}), Geo<:(NamedTuple{(:cos_zenith,), <:Tuple{Any}}), C<:NumericalRadiation.PhysicalConstants}

Column (i, j) of model as NumericalRadiation's ColumnAtmosphere on the host: the layer and interface states that the layer pass of rtm computes (with the extension pressures of the batch of columns that holds row j, computed here), the gas amounts of layer_gas_amounts, the surface temperature and emissivity at (i, j), the column's cosine of the solar zenith angle, and the thermodynamic constants of model as NumericalRadiation's PhysicalConstants.

source
BreezeNumericalRadiationExt.column_batches — Method
column_batches(
    workspace::BreezeNumericalRadiationExt.ColumnWorkspace,
    grid
) -> Union{Base.Generator{<:Any, F} where F<:(BreezeNumericalRadiationExt.var"#column_batches##0#column_batches##1"{Int64}), DiskArrays.DiskGenerator{I, F} where {I<:DiskArrays.AbstractDiskArray, F<:(BreezeNumericalRadiationExt.var"#column_batches##0#column_batches##1"{Int64})}}

The batches of the rows of grid that workspace holds one at a time: the (row_offset, size) of each, with row_offset the number of grid rows before the batch and size = (Nx, rows) the columns it solves. Every batch is full, so the column kernels compile for one size: when the rows do not divide Ny, the final batch overlaps the one before it (as for the RRTMGP optics), and the overlapping columns are solved twice.

source
BreezeNumericalRadiationExt.compute_extension_pressure! — Method
compute_extension_pressure!(
    state::BreezeNumericalRadiationExt.ColumnState,
    batch_size
)

Integrate the extension layers' hydrostatic pressures of the batch_size = (Nx, rows) columns of the batch of state upward from the grid's top face, with the virtual temperature of the anchored extension profile, into state.extension_pressure; nothing to do without an extension.

source
BreezeNumericalRadiationExt.compute_layer_state! — Method
compute_layer_state!(
    workspace,
    state,
    gas_model,
    batch_size
)

Compute the gas optics stencil, gas amounts and water paths of every layer and the temperature of every interface of the batch_size = (Nx, rows) columns of the batch of state, and store them in workspace for the column kernel.

source
BreezeNumericalRadiationExt.extension_layer_state — Method
extension_layer_state(
    i,
    j,
    m,
    grid,
    state,
    extension
) -> NamedTuple{(:pressure, :temperature, :dry_air, :water_vapor, :ozone, :liquid_water_path, :ice_water_path), <:NTuple{7, Any}}

The state of extension layer m of column (i, j), in the form of grid_layer_state: the anchored temperature, the log-mean of the hydrostatic pressures on its faces, the dry-air amount Δp / (g mᵈ), the water vapor and ozone as their mole fractions times it, and no cloud.

source
BreezeNumericalRadiationExt.grid_layer_state — Method
grid_layer_state(
    i,
    j,
    k,
    grid,
    state
) -> NamedTuple{(:pressure, :temperature, :dry_air, :water_vapor, :ozone, :liquid_water_path, :ice_water_path), <:NTuple{7, Any}}

Pressure, temperature, molar amounts (mol m⁻²) of dry air, water vapor and ozone, and liquid and ice water paths (kg m⁻²) of grid cell k of column (i, j).

The gas amounts follow the "dry" convention of the ecCKD tables: the dry-air amount is the layer's total mass over the dry molar mass, ρ Δz / mᵈ (Δp / (g mᵈ) for a hydrostatic layer), and the water vapor ρ qᵛ Δz / mᵛ is counted on top of it, so the ratio of the two is the mole fraction the tables are indexed by. NumericalRadiation's CKDMIP and RFMIP validation passes only with this convention; the moist form ρ (1 - qᵗ) Δz / mᵈ biases the surface downwelling longwave by -0.2 W m⁻².

source
BreezeNumericalRadiationExt.interface_temperature — Method
interface_temperature(i, j, k, grid, state)

The temperature on column interface k (top-down) of column (i, j): on the grid's faces the interpolated temperature, above it the interpolated temperature of the anchored extension layers. The top of the atmosphere radiates at the temperature of the top layer.

source
BreezeNumericalRadiationExt.layer_gas_amounts — Method
layer_gas_amounts(
    layer,
    mole_fractions
) -> NamedTuple{(:dry_air, :H₂O, :O₃, :CO₂, :CH₄, :N₂O, :CFC₁₁, :CFC₁₂), <:NTuple{8, Any}}

The scalar gas amounts (mol m⁻²) of layer (a layer_state) as a NamedTuple keyed by ECCKD_GAS_NAMES: its dry air, water vapor and ozone, and the well-mixed gases as mole_fractions times the dry air. The keys are the gas names of the ecCKD tables, which NumericalRadiation looks the gases up by.

source
BreezeNumericalRadiationExt.layer_state — Method
layer_state(
    i,
    j,
    k,
    grid,
    state
) -> NamedTuple{(:pressure, :temperature, :dry_air, :water_vapor, :ozone, :liquid_water_path, :ice_water_path), <:NTuple{7, Any}}

The state of column layer k (top-down) of column (i, j): a grid cell or, above the grid top, an extension layer.

source
BreezeNumericalRadiationExt.load_cloud_optics — Method
load_cloud_optics(
    FT,
    tables::CloudScatteringTables,
    gas_model,
    liquid_radius,
    ice_radius,
    arch
)

Read the liquid and ice scattering tables of tables::CloudScatteringTables and map them onto the longwave and shortwave g points of the gas model selected by gas_model (a reference selector or (longwave = path, shortwave = path) definition files) at the constant effective radii liquid_radius and ice_radius (m), returning (longwave, shortwave) (liquid, ice) pairs of NumericalRadiation.SpectralCloudOptics in float type FT on architecture arch.

Clear sky (tables::Nothing) returns (nothing, nothing): the layer optics then add no cloud.

source
BreezeNumericalRadiationExt.materialize_overlying_atmosphere — Method
materialize_overlying_atmosphere(
    extension::OverlyingAtmosphereColumn,
    grid,
    background::BackgroundAtmosphere
) -> Union{Nothing, OverlyingAtmosphereColumn}

Materialize extension on the geometrically stretched layers between the top face of grid and extension.top (see overlying_atmosphere_faces): the layers' thicknesses and centers and the profiles sampled at the centers, in the grid's float type and on its architecture, with the ozone profile of background when the extension has none. Returns nothing when the grid already reaches extension.top.

source
BreezeNumericalRadiationExt.physical_constants — Method
physical_constants(
    FT,
    constants::ThermodynamicConstants,
    gas_model,
    solar_constant
) -> NumericalRadiation.PhysicalConstants

NumericalRadiation's PhysicalConstants in float type FT with the values of Breeze's constants::ThermodynamicConstants (gravity, the dry-air heat capacity, the molar masses and the gas constants), the Stefan–Boltzmann constant of gas_model (which carries it for its gray source), and solar_constant: the constants the column kernel uses, handed to NumericalRadiation's array path so that both paths see the same values.

source
BreezeNumericalRadiationExt.solve_columns! — Method
solve_columns!(
    rtm::RadiativeTransferModel{<:Any, <:Any, <:Any, <:BackgroundAtmosphere, <:BreezeNumericalRadiationExt.ColumnWorkspace},
    state,
    batch_size
)

Solve the longwave and shortwave fluxes of the batch_size = (Nx, rows) columns of the batch of state, whose layer state the layer pass has stored in rtm's workspace: per column, stream the g points of the no-scattering longwave solver and of the two-stream shortwave solver through the column's layer optics, accumulating the fluxes into the four flux fields of rtm. At night the shortwave irradiance S₀ max(μ₀, 0) is zero and the shortwave fluxes vanish without a branch.

source