Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
glwagner committed Dec 10, 2024
2 parents 51ba207 + aba98ca commit 46f2b94
Show file tree
Hide file tree
Showing 48 changed files with 1,290 additions and 505 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Oceananigans"
uuid = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09"
authors = ["Climate Modeling Alliance and contributors"]
version = "0.94.3"
version = "0.94.4"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
Expand Down
2 changes: 2 additions & 0 deletions src/AbstractOperations/binary_operations.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Oceananigans.Operators

const binary_operators = Set()

struct BinaryOperation{LX, LY, LZ, O, A, B, IA, IB, G, T} <: AbstractOperation{LX, LY, LZ, G, T}
Expand Down
172 changes: 52 additions & 120 deletions src/AbstractOperations/grid_metrics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,121 +2,32 @@ using Adapt
using Oceananigans.Operators
using Oceananigans.Grids: AbstractGrid
using Oceananigans.Fields: AbstractField, default_indices, location
using Oceananigans.Operators: Δx, Δy, Δz, Ax, Δλ, Δφ, Ay, Az, volume

import Oceananigans.Grids: xspacings, yspacings, zspacings, λspacings, φspacings

abstract type AbstractGridMetric end

struct XSpacingMetric <: AbstractGridMetric end
struct YSpacingMetric <: AbstractGridMetric end
struct ZSpacingMetric <: AbstractGridMetric end

metric_function_prefix(::XSpacingMetric) = :Δx
metric_function_prefix(::YSpacingMetric) = :Δy
metric_function_prefix(::ZSpacingMetric) = :Δz

struct XAreaMetric <: AbstractGridMetric end
struct YAreaMetric <: AbstractGridMetric end
struct ZAreaMetric <: AbstractGridMetric end

metric_function_prefix(::XAreaMetric) = :Ax
metric_function_prefix(::YAreaMetric) = :Ay
metric_function_prefix(::ZAreaMetric) = :Az

struct VolumeMetric <: AbstractGridMetric end

metric_function_prefix(::VolumeMetric) = :V

# Convenient instances for users
const Δx = XSpacingMetric()
const Δy = YSpacingMetric()

"""
Δz = ZSpacingMetric()
Instance of `ZSpacingMetric` that generates `BinaryOperation`s
between `AbstractField`s and the vertical grid spacing evaluated
at the same location as the `AbstractField`.
`Δx` and `Δy` play a similar role for horizontal grid spacings.
Example
=======
```jldoctest
julia> using Oceananigans
julia> using Oceananigans.AbstractOperations: Δz
julia> c = CenterField(RectilinearGrid(size=(1, 1, 1), extent=(1, 2, 3)));
julia> c_dz = c * Δz # returns BinaryOperation between Field and GridMetricOperation
BinaryOperation at (Center, Center, Center)
├── grid: 1×1×1 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 1×1×1 halo
└── tree:
* at (Center, Center, Center)
   ├── 1×1×1 Field{Center, Center, Center} on RectilinearGrid on CPU
   └── Δzᶜᶜᶜ at (Center, Center, Center)
julia> c .= 1;
julia> c_dz[1, 1, 1]
3.0
```
"""
const Δz = ZSpacingMetric()

const Ax = XAreaMetric()
const Ay = YAreaMetric()
const Az = ZAreaMetric()

"""
volume = VolumeMetric()
Instance of `VolumeMetric` that generates `BinaryOperation`s
between `AbstractField`s and their cell volumes. Summing
this `BinaryOperation` yields an integral of `AbstractField`
over the domain.
Example
=======
```jldoctest
julia> using Oceananigans
julia> using Oceananigans.AbstractOperations: volume
julia> c = CenterField(RectilinearGrid(size=(2, 2, 2), extent=(1, 2, 3)));
julia> c .= 1;
julia> c_dV = c * volume
BinaryOperation at (Center, Center, Center)
├── grid: 2×2×2 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 2×2×2 halo
└── tree:
* at (Center, Center, Center)
   ├── 2×2×2 Field{Center, Center, Center} on RectilinearGrid on CPU
   └── Vᶜᶜᶜ at (Center, Center, Center)
julia> c_dV[1, 1, 1]
0.75
julia> sum(c_dV)
6.0
```
"""
const volume = VolumeMetric()
const AbstractGridMetric = Union{typeof(Δx),
typeof(Δy),
typeof(Δz),
typeof(Δλ),
typeof(Δφ),
typeof(Ax),
typeof(Ay),
typeof(Az),
typeof(volume)} # Do we want it to be `volume` or just `V` like in the Operators module?

"""
metric_function(loc, metric::AbstractGridMetric)
Return the function associated with `metric::AbstractGridMetric`
at `loc`ation.
Return the function associated with `metric::AbstractGridMetric` at `loc`ation.
"""
function metric_function(loc, metric::AbstractGridMetric)
function metric_function(loc, metric)
code = Tuple(interpolation_code(ℓ) forin loc)
prefix = metric_function_prefix(metric)
metric_function_symbol = Symbol(prefix, code...)
if metric isa typeof(volume)
metric_function_symbol = Symbol(:V, code...)
else
metric_function_symbol = Symbol(metric, code...)
end
return getglobal(@__MODULE__, metric_function_symbol)
end

Expand All @@ -137,12 +48,33 @@ on_architecture(to, gm::GridMetricOperation{LX, LY, LZ}) where {LX, LY, LZ} =
GridMetricOperation{LX, LY, LZ}(on_architecture(to, gm.metric),
on_architecture(to, gm.grid))


@inline Base.getindex(gm::GridMetricOperation, i, j, k) = gm.metric(i, j, k, gm.grid)

indices(::GridMetricOperation) = default_indices(3)

# Special constructor for BinaryOperation
"""
GridMetricOperation(L, metric, grid)
Instance of `GridMetricOperation` that generates `BinaryOperation`s between `AbstractField`s and the metric `metric`
at the same location as the `AbstractField`.
Example
=======
```jldoctest
julia> using Oceananigans
julia> using Oceananigans.Operators: Δz
julia> c = CenterField(RectilinearGrid(size=(1, 1, 1), extent=(1, 2, 3)));
julia> c_dz = c * Δz; # returns BinaryOperation between Field and GridMetricOperation
julia> c .= 1;
julia> c_dz[1, 1, 1]
3.0
```
"""
GridMetricOperation(L, metric, grid) = GridMetricOperation{L[1], L[2], L[3]}(metric_function(L, metric), grid)

#####
Expand All @@ -165,13 +97,13 @@ julia> grid = RectilinearGrid(size=(2, 4, 8), extent=(1, 1, 1));
julia> xspacings(grid, Center(), Center(), Center())
KernelFunctionOperation at (Center, Center, Center)
├── grid: 2×4×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 2×3×3 halo
├── kernel_function: xspacing (generic function with 27 methods)
├── kernel_function: Δx (generic function with 29 methods)
└── arguments: ("Center", "Center", "Center")
```
"""
function xspacings(grid, ℓx, ℓy, ℓz)
LX, LY, LZ = map(typeof, (ℓx, ℓy, ℓz))
Δx_op = KernelFunctionOperation{LX, LY, LZ}(xspacing, grid, ℓx, ℓy, ℓz)
Δx_op = KernelFunctionOperation{LX, LY, LZ}(Δx, grid, ℓx, ℓy, ℓz)
return Δx_op
end

Expand All @@ -191,13 +123,13 @@ julia> grid = RectilinearGrid(size=(2, 4, 8), extent=(1, 1, 1));
julia> yspacings(grid, Center(), Face(), Center())
KernelFunctionOperation at (Center, Face, Center)
├── grid: 2×4×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 2×3×3 halo
├── kernel_function: yspacing (generic function with 27 methods)
├── kernel_function: Δy (generic function with 29 methods)
└── arguments: ("Center", "Face", "Center")
```
"""
function yspacings(grid, ℓx, ℓy, ℓz)
LX, LY, LZ = map(typeof, (ℓx, ℓy, ℓz))
Δy_op = KernelFunctionOperation{LX, LY, LZ}(yspacing, grid, ℓx, ℓy, ℓz)
Δy_op = KernelFunctionOperation{LX, LY, LZ}(Δy, grid, ℓx, ℓy, ℓz)
return Δy_op
end

Expand All @@ -217,21 +149,21 @@ julia> grid = RectilinearGrid(size=(2, 4, 8), extent=(1, 1, 1));
julia> zspacings(grid, Center(), Center(), Face())
KernelFunctionOperation at (Center, Center, Face)
├── grid: 2×4×8 RectilinearGrid{Float64, Periodic, Periodic, Bounded} on CPU with 2×3×3 halo
├── kernel_function: zspacing (generic function with 27 methods)
├── kernel_function: Δz (generic function with 28 methods)
└── arguments: ("Center", "Center", "Face")
```
"""
function zspacings(grid, ℓx, ℓy, ℓz)
LX, LY, LZ = map(typeof, (ℓx, ℓy, ℓz))
Δz_op = KernelFunctionOperation{LX, LY, LZ}(zspacing, grid, ℓx, ℓy, ℓz)
Δz_op = KernelFunctionOperation{LX, LY, LZ}(Δz, grid, ℓx, ℓy, ℓz)
return Δz_op
end

"""
λspacings(grid, ℓx, ℓy, ℓz)
Return a `KernelFunctionOperation` that computes the grid spacings for `grid`
in the ``z`` direction at location `ℓx, ℓy, ℓz`.
in the ``λ`` direction at location `ℓx, ℓy, ℓz`.
Examples
========
Expand All @@ -246,21 +178,21 @@ julia> grid = LatitudeLongitudeGrid(size=(36, 34, 25),
julia> λspacings(grid, Center(), Face(), Center())
KernelFunctionOperation at (Center, Face, Center)
├── grid: 36×34×25 LatitudeLongitudeGrid{Float64, Periodic, Bounded, Bounded} on CPU with 3×3×3 halo and with precomputed metrics
├── kernel_function: λspacing (generic function with 5 methods)
├── kernel_function: Δλ (generic function with 29 methods)
└── arguments: ("Center", "Face", "Center")
```
"""
function λspacings(grid, ℓx, ℓy, ℓz)
LX, LY, LZ = map(typeof, (ℓx, ℓy, ℓz))
Δλ_op = KernelFunctionOperation{LX, LY, LZ}(λspacing, grid, ℓx, ℓy, ℓz)
Δλ_op = KernelFunctionOperation{LX, LY, LZ}(Δλ, grid, ℓx, ℓy, ℓz)
return Δλ_op
end

"""
φspacings(grid, ℓx, ℓy, ℓz)
Return a `KernelFunctionOperation` that computes the grid spacings for `grid`
in the ``z`` direction at location `ℓx, ℓy, ℓz`.
in the ``φ`` direction at location `ℓx, ℓy, ℓz`.
Examples
========
Expand All @@ -275,13 +207,13 @@ julia> grid = LatitudeLongitudeGrid(size=(36, 34, 25),
julia> φspacings(grid, Center(), Face(), Center())
KernelFunctionOperation at (Center, Face, Center)
├── grid: 36×34×25 LatitudeLongitudeGrid{Float64, Periodic, Bounded, Bounded} on CPU with 3×3×3 halo and with precomputed metrics
├── kernel_function: φspacing (generic function with 5 methods)
├── kernel_function: Δφ (generic function with 29 methods)
└── arguments: ("Center", "Face", "Center")
```
"""
function φspacings(grid, ℓx, ℓy, ℓz)
LX, LY, LZ = map(typeof, (ℓx, ℓy, ℓz))
Δφ_op = KernelFunctionOperation{LX, LY, LZ}(φspacing, grid, ℓx, ℓy, ℓz)
Δφ_op = KernelFunctionOperation{LX, LY, LZ}(Δφ, grid, ℓx, ℓy, ℓz)
return Δφ_op
end

Expand Down
2 changes: 1 addition & 1 deletion src/Biogeochemistry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Update biogeochemical state variables. Called at the end of update_state!.
"""
update_biogeochemical_state!(bgc, model) = nothing

@inline biogeochemical_drift_velocity(bgc, val_tracer_name) = (u = ZeroField(), v = ZeroField(), w = ZeroField())
@inline biogeochemical_drift_velocity(bgc, val_tracer_name) = nothing
@inline biogeochemical_auxiliary_fields(bgc) = NamedTuple()

"""
Expand Down
1 change: 1 addition & 0 deletions src/BoundaryConditions/BoundaryConditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ include("fill_halo_regions_nothing.jl")
include("apply_flux_bcs.jl")

include("update_boundary_conditions.jl")
include("polar_boundary_condition.jl")

include("flat_extrapolation_open_boundary_matching_scheme.jl")
end # module
20 changes: 13 additions & 7 deletions src/BoundaryConditions/field_boundary_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ end
FieldBoundaryConditions(indices::Tuple, bcs::FieldBoundaryConditions) =
FieldBoundaryConditions(indices, (getproperty(bcs, side) for side in propertynames(bcs))...)


FieldBoundaryConditions(indices::Tuple, ::Nothing) = nothing

window_boundary_conditions(::Colon, left, right) = left, right
Expand Down Expand Up @@ -178,6 +177,13 @@ function regularize_immersed_boundary_condition(ibc, grid, loc, field_name, args
return NoFluxBoundaryCondition()
end

regularize_west_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_east_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_south_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_north_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_bottom_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)
regularize_top_boundary_condition(bc, args...) = regularize_boundary_condition(bc, args...)

# regularize default boundary conditions
function regularize_boundary_condition(default::DefaultBoundaryCondition, grid, loc, dim, args...)
default_bc = default_prognostic_bc(topology(grid, dim)(), loc[dim](), default)
Expand Down Expand Up @@ -212,12 +218,12 @@ function regularize_field_boundary_conditions(bcs::FieldBoundaryConditions,

loc = assumed_field_location(field_name)

west = regularize_boundary_condition(bcs.west, grid, loc, 1, LeftBoundary, prognostic_names)
east = regularize_boundary_condition(bcs.east, grid, loc, 1, RightBoundary, prognostic_names)
south = regularize_boundary_condition(bcs.south, grid, loc, 2, LeftBoundary, prognostic_names)
north = regularize_boundary_condition(bcs.north, grid, loc, 2, RightBoundary, prognostic_names)
bottom = regularize_boundary_condition(bcs.bottom, grid, loc, 3, LeftBoundary, prognostic_names)
top = regularize_boundary_condition(bcs.top, grid, loc, 3, RightBoundary, prognostic_names)
west = regularize_west_boundary_condition(bcs.west, grid, loc, 1, LeftBoundary, prognostic_names)
east = regularize_east_boundary_condition(bcs.east, grid, loc, 1, RightBoundary, prognostic_names)
south = regularize_south_boundary_condition(bcs.south, grid, loc, 2, LeftBoundary, prognostic_names)
north = regularize_north_boundary_condition(bcs.north, grid, loc, 2, RightBoundary, prognostic_names)
bottom = regularize_bottom_boundary_condition(bcs.bottom, grid, loc, 3, LeftBoundary, prognostic_names)
top = regularize_top_boundary_condition(bcs.top, grid, loc, 3, RightBoundary, prognostic_names)

immersed = regularize_immersed_boundary_condition(bcs.immersed, grid, loc, field_name, prognostic_names)

Expand Down
Loading

1 comment on commit 46f2b94

@simone-silvestri
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happened here?

Please sign in to comment.