Background fields
BackgroundFields are velocity and tracer fields around which the resolved velocity and tracer fields evolve. Only the advective terms associated with the interaction between background and resolved fields are included. For example, tracer advection is described by
where model.tracers.c.
When a background field
When both a background field velocity field
Notice that the term
Model compatibility
BackgroundFields are only supported by NonhydrostaticModel.
Specifying background fields
BackgroundFields are defined by functions of
using Oceananigans
U(x, y, z, t) = 0.2 * z
grid = RectilinearGrid(size=(1, 1, 1), extent=(1, 1, 1))
model = NonhydrostaticModel(grid; background_fields = (u=U,))
model.background_fields.velocities.u
# output
FunctionField located at (Face, Center, Center)
├── func: U (generic function with 1 method)
├── grid: 1×1×1 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×1 halo
├── clock: Clock{Float64, Float64}(time=0 seconds, iteration=0, last_Δt=Inf days)
└── parameters: nothingBackgroundFields are specified by passing them to the kwarg background_fields in the NonhydrostaticModel constructor. The kwarg background_fields expects a NamedTuple of fields, which are internally sorted into velocities and tracers, wrapped in FunctionFields, and assigned their appropriate locations.
BackgroundFields with parameters require using the BackgroundField wrapper:
using Oceananigans
parameters = (α=3.14, N=1.0, f=0.1)
# Background fields are defined via function of x, y, z, t, and optional parameters
U(x, y, z, t, α) = α * z
B(x, y, z, t, p) = - p.α * p.f * y + p.N^2 * z
U_field = BackgroundField(U, parameters=parameters.α)
B_field = BackgroundField(B, parameters=parameters)
# output
BackgroundField{typeof(B), @NamedTuple{α::Float64, N::Float64, f::Float64}}
├── func: B (generic function with 1 method)
└── parameters: (α = 3.14, N = 1.0, f = 0.1)When inserted into NonhydrostaticModel, we get
grid = RectilinearGrid(size=(1, 1, 1), extent=(1, 1, 1))
model = NonhydrostaticModel(grid; background_fields = (u=U_field, b=B_field),
tracers=:b, buoyancy=BuoyancyTracer())
model.background_fields.tracers.b
# output
FunctionField located at (Center, Center, Center)
├── func: B (generic function with 1 method)
├── grid: 1×1×1 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×1 halo
├── clock: Clock{Float64, Float64}(time=0 seconds, iteration=0, last_Δt=Inf days)
└── parameters: (α = 3.14, N = 1.0, f = 0.1)Turbulent fluxes of background fields
By default, only the advective interaction between the background and resolved fields is included (as described above). Turbulent closure fluxes acting on background fields are neglected.
To include them, construct BackgroundFields explicitly with background_closure_fluxes=true and pass it to the model:
using Oceananigans
using Oceananigans.Models.NonhydrostaticModels: BackgroundFields
U(x, y, z, t) = 0.2 * z # linear shear background velocity
background_fields = BackgroundFields(background_closure_fluxes=true, u=U)
grid = RectilinearGrid(size=(1, 1, 1), extent=(1, 1, 1))
model = NonhydrostaticModel(grid; background_fields, closure=ScalarDiffusivity(ν=1e-4, κ=1e-5))
model.background_fields.velocities.u
# output
FunctionField located at (Face, Center, Center)
├── func: U (generic function with 1 method)
├── grid: 1×1×1 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×1 halo
├── clock: Clock{Float64, Float64}(time=0 seconds, iteration=0, last_Δt=Inf days)
└── parameters: nothingThis is relevant when background gradients are large enough that diffusive fluxes from the background field contribute non-negligibly to the resolved dynamics — for example, in strongly sheared background flows with active turbulence closures.