Boundary conditions
A boundary condition is applied to each field, dimension, and endpoint. There are left and right (or bottom and top) boundary conditions for each of the x, y, and z dimensions so each field is associated with 6 boundary conditions. Each of these boundary conditions may be specified individually. Each boundary condition can be specified via a constant value, an array, or a function.
See Numerical implementation of boundary conditions for more details.
Be careful to ensure that you don't set up a model with inconsistent boundary conditions. For example, periodic boundary conditions should remain imposed on all fields and endpoints for periodic dimensions, and velocities normal to a wall (e.g. vertical velocity w with walls at the top and bottom) must have no-penetration boundary conditions.
Types of boundary conditions
Notice that open boundary conditions and radiation boundary conditions can be imposed via flux or value boundary conditions defined by a function or array.
Default boundary conditions
By default, periodic boundary conditions are applied on all fields along periodic dimensions. All other boundary conditions are no-flux, except for velocities normal to a wall which get no-penetration boundary conditions.
Boundary condition structures
Oceananigans uses a hierarchical structure to expressing boundary conditions.
- A
BoundaryCondition
is associated with every field, dimension, and endpoint. - Boundary conditions specifying the condition at the left and right endpoints (or top and bottom endpoints) are grouped into
CoordinateBoundaryConditions
. - A set of three
CoordinateBoundaryConditions
specifying the boundary conditions along the x, y, and z dimensions for a single field are grouped into aFieldBoundaryConditions
named tuple. - A set of
FieldBoundaryConditions
, one for each field, are grouped together into a named tuple and passed to theModel
constructor.
Boundary conditions are defined at model construction time by passing a named tuple of FieldBoundaryConditions
specifying boundary conditions on every field: velocities ($u$, $v$, $w$) and all tracers.
Typically you only want to impose a few boundary conditions, in which case it's useful to use convenience constructors such as HorizontallyPeriodicBCs
when constructing horizontally periodic boundary conditions for a field and HorizontallyPeriodicSolutionBCs
when constructing horizontally periodic boundary conditions for a model. Also see ChannelBCs
and ChannelSolutionBCs
.
See the sections below for more details. The examples and verification experiments also provide examples for setting up many difference kinds of boundary conditions.
Creating individual boundary conditions
Some examples of creating individual boundary conditions:
- A constant Value (Dirchlet) boundary condition, perhaps representing a constant temperature at some boundary.
constant_T_bc = BoundaryCondition(Value, 20)
BoundaryCondition: type=Value, condition=20
- A constant flux boundary condition, perhaps representing a constant wind stress at some boundary such as the ocean surface.
ρ₀ = 1027 # Reference density [kg/m³]
τₓ = 0.08 # Wind stress [N/m²]
wind_stress_bc = BoundaryCondition(Flux, τₓ/ρ₀)
BoundaryCondition: type=Flux, condition=7.789678675754625e-5
- A spatially varying (white noise) cooling flux to be imposed at some boundary. Note that the boundary condition is given by the array
Q
here. When running on the GPU,Q
must be converted to aCuArray
.
Nx = Ny = 16 # Number of grid points.
ρ₀ = 1027 # Reference density [kg/m³]
cₚ = 4000 # Heat capacity of water at constant pressure [J/kg/K]
Q = randn(Nx, Ny) ./ (ρ₀ * cₚ)
white_noise_T_bc = BoundaryCondition(Flux, Q)
BoundaryCondition: type=Flux, condition=[4.926999610161019e-8 2.0766171958884423e-8 -1.1643457286270756e-7 4.719731693193799e-7 2.1515110198922039e-7 6.383004131265455e-8 8.063447845424635e-8 1.8814843253521056e-7 -2.235030102947714e-7 3.0006353606302377e-7 9.617909114466926e-8 1.0569921375408993e-7 -1.366869159925887e-7 2.891701590476552e-7 -4.332286671187095e-7 2.7012898470988944e-7; -1.684254791359542e-7 -1.2896434074050575e-7 1.93620566059667e-8 3.072634928830686e-7 -4.880739172405166e-8 -1.966122538495756e-7 5.578283136378323e-7 2.774355344541829e-7 1.2328909571323918e-7 3.132788897302968e-7 1.9675895141853987e-7 1.6014336446873806e-7 -3.6389933354697305e-7 -9.07353419163106e-8 1.382544436687941e-7 2.1898816696304774e-7; 1.5172790129919822e-7 2.636783845932815e-7 8.435690017206132e-8 3.5793888628111745e-7 -2.018430603697911e-7 -5.530481752688696e-8 3.7267111958556144e-7 2.724724218747869e-7 2.1029309201557424e-8 -4.1037227226698407e-7 4.504138151089493e-7 -2.781891560925929e-7 -2.502546624446021e-7 -8.656786061595952e-8 9.158236538350607e-8 -1.2292880341516375e-7; -1.5123545248377698e-7 -1.399717227239595e-7 -1.0062763797590766e-7 1.8587913338659088e-8 2.1042814694013625e-7 -2.029679620375007e-7 2.502191618716448e-7 -2.6869644346114647e-7 -1.0937902869499375e-7 -1.372394271749857e-7 4.566270736343835e-8 1.330187073990753e-8 -1.9702755306316695e-7 2.349606542788728e-7 4.348129142412905e-7 -1.1837970236841479e-7; 1.9218433458640246e-7 1.9166083195281728e-7 2.774348028564653e-7 2.968386388561345e-7 2.992280951232792e-7 -1.5616177496934664e-7 6.596040454061136e-7 -2.3590344869215227e-8 3.903103037682611e-7 -3.462954533421291e-7 -3.049232555784883e-7 1.1665162639384006e-7 -2.2019138896261818e-7 2.1709685875661505e-7 -1.2440453252635213e-7 1.894295533107364e-8; 1.5194897227750494e-7 -2.112544516508757e-7 1.636194904719126e-7 -3.046440114325844e-7 -2.3514048813086577e-7 -3.237604598109776e-7 3.115701186741502e-7 1.4964369114464004e-7 -7.09728556335275e-8 -3.6708352913789476e-7 -3.387344838115505e-7 2.9970930823339284e-7 -1.0379935165302013e-7 1.8179375192753225e-7 4.33459739691843e-7 -1.3736661147788173e-8; -8.66579430943387e-8 -4.421079568157016e-8 -2.154967044733889e-9 -2.4425224018786297e-7 2.7511340806119734e-7 3.3697624890485786e-7 -1.307755136563798e-8 2.4285121298238795e-7 -1.4751077968393045e-7 1.7485266541906048e-7 -2.1905588990238702e-7 -5.001474879019152e-8 4.825577596116903e-7 -2.632184282550969e-7 -4.7681675579188055e-7 -2.649784043104761e-7; 4.4489650850631284e-7 -4.302841409537252e-8 3.671362024918616e-8 1.569784242035872e-7 -2.1743115733281015e-7 -6.194763812191634e-8 4.860473795737506e-7 2.2894676243545098e-7 -2.9030176193675076e-7 4.950955753040145e-8 -4.992932344632826e-8 1.9618060825765708e-7 3.4781170388586425e-7 2.3533789210350093e-7 3.850446275523473e-8 -4.748752574482355e-8; -1.2146550206256723e-7 -1.2318426216925936e-7 -8.459466072741217e-8 -3.0397995411123665e-7 6.733889726954662e-8 -4.4778760744852726e-7 -6.114538565831286e-8 7.194009564345187e-8 1.0721031641361757e-7 -3.5911094987429946e-7 6.626212820268886e-8 -3.993095899241393e-8 8.448189787022476e-8 3.839100162955952e-7 2.77854994469647e-7 9.00312003141937e-8; -6.670674922163773e-8 -1.5721702113152624e-8 1.9399051659501637e-7 -3.799641823048931e-7 -9.54564063010317e-8 1.2724475179322343e-7 2.7753482199965482e-8 -2.2436235741936964e-7 4.152236238942351e-7 -1.4936653462735415e-7 1.3000949809064279e-7 6.207912718403556e-7 1.1195206292114052e-7 5.182620623599242e-7 -1.2329647325802174e-7 -3.290744822188762e-8; -5.977955039115372e-8 2.0680880875394024e-7 9.651849354301752e-8 -1.2517331661852451e-7 -3.423188679959834e-7 3.099404065805671e-7 -2.0972340027296518e-7 -1.367399816249844e-7 -2.242841634487496e-7 -5.23359251791737e-7 -3.8784274195816865e-7 2.361562713094052e-9 4.412099418889843e-7 2.6537719806409256e-8 1.6078356227283677e-8 6.565836396333691e-8; -9.503081063792376e-8 2.0880378973494568e-7 3.6444177388458364e-7 3.253292199420296e-7 -4.475948186549955e-7 1.097384764822597e-7 3.3065483908062085e-7 5.061934704413197e-8 -6.551452363013066e-8 -1.8863863914578097e-7 -2.6311541380182915e-7 -3.061918787720692e-7 -1.988649163487694e-7 1.59522525576049e-7 9.176348835750079e-8 -6.136238159019797e-7; 8.715908016540653e-8 -2.268483374229665e-7 -5.340168830799568e-7 7.532148822347095e-7 2.9728316448910013e-8 1.0427265440960775e-9 -1.5724647323938292e-7 3.2706032396083084e-7 4.986179839947894e-7 2.1344217351508638e-7 -2.6362805262380786e-7 -1.48322518888732e-7 -6.304083529226176e-7 -2.389311037086304e-8 7.590761420305527e-8 -3.574979869885613e-8; 4.0963977648356824e-7 -1.1462023344855877e-7 3.9049671469540717e-7 9.046362306326393e-8 4.008616419722497e-7 -1.1129504593610562e-7 -2.2543319225776233e-7 2.63346767353527e-7 2.1200335150434144e-7 1.897052823839317e-7 4.811493862426515e-8 -8.306361594273524e-8 1.8109960021113025e-7 -1.0765207788854553e-7 -2.8436291508717143e-8 -1.9865188440712506e-7; -3.5500471064455814e-8 1.8770932821001534e-7 6.185953377518442e-8 3.950995333565914e-7 -6.36096542614665e-7 1.436541864649168e-7 3.0956294670581436e-7 9.679463149126173e-9 5.644488470090447e-7 1.7174450216795213e-7 -7.621242233820063e-8 -2.0159234024915023e-7 -1.2946741415811693e-7 5.430248717953878e-8 -2.525209375493045e-7 -2.3180630812835544e-7; 4.019712443173313e-8 1.2008296314030077e-7 1.8917626834781295e-7 9.069691548060632e-9 3.659733941378589e-7 3.0091936449222254e-7 8.800295769677759e-8 -1.7402245432582255e-7 3.089219034704156e-8 -2.4476042482005935e-8 -1.1279353415556108e-7 -3.1826186280093245e-8 2.3436663426953466e-7 1.0025701553489523e-7 -3.45525089848044e-7 -8.267687328121957e-10]
Specifying boundary conditions with functions
You can also specify the boundary condition via a function. For z boundary conditions the function will be called with the signature
f(i, j, grid, t, U, C, params)
where i, j
is the grid index, grid
is model.grid
, t
is the model.clock.time
, U
is the named tuple model.velocities
, C
is the named tuple C.tracers
, and params
is the user-defined model.parameters
. The signature is similar for x and y boundary conditions expect that i, j
is replaced with j, k
and i, k
respectively.
We can add a fourth example now:
- A spatially varying and time-dependent heating representing perhaps a localized source of heating modulated by a diurnal cycle.
@inline Q(i, j, grid, t, U, C, params) = @inbounds exp(-(grid.xC[i]^2 + grid.yC[j]^2)) * sin(2π*t)
localized_heating_bc = BoundaryCondition(Flux, Q)
BoundaryCondition: type=Flux, condition=Q
For performance reasons, you should define all functions used in boundary conditions as inline functions via the @inline
macro. If any arrays are accessed within the function, disabling bounds-checking with @inbounds
can also speed things up.
Specifying boundary conditions on a field
To, for example, create a set of horizontally periodic field boundary conditions
T_bcs = HorizontallyPeriodicBCs( top = BoundaryCondition(Value, 20),
bottom = BoundaryCondition(Gradient, 0.01))
Oceananigans.FieldBoundaryConditions (NamedTuple{(:x, :y, :z)}), with boundary conditions
├── x: CoordinateBoundaryConditions{BoundaryCondition{Periodic,Nothing},BoundaryCondition{Periodic,Nothing}}
├── y: CoordinateBoundaryConditions{BoundaryCondition{Periodic,Nothing},BoundaryCondition{Periodic,Nothing}}
└── z: CoordinateBoundaryConditions{BoundaryCondition{Gradient,Float64},BoundaryCondition{Value,Int64}}
which will create a FieldBoundaryConditions
object for temperature T appropriate for horizontally periodic model configurations where the x and y boundary conditions are all periodic.
Specifying model boundary conditions
A named tuple of FieldBoundaryConditions
objects must be passed to the Model constructor specifying boundary conditions on all fields. To, for example, impose non-default boundary conditions on the u-velocity and temperature
u_bcs = HorizontallyPeriodicBCs( top = BoundaryCondition(Value, 0.1),
bottom = BoundaryCondition(Value, -0.1))
T_bcs = HorizontallyPeriodicBCs( top = BoundaryCondition(Value, 20),
bottom = BoundaryCondition(Gradient, 0.01))
model_bcs = HorizontallyPeriodicSolutionBCs(u=u_bcs, T=T_bcs)
model = Model(grid=RegularCartesianGrid(size=(16, 16, 16), length=(1, 1, 1)),
boundary_conditions=model_bcs)