Skip to content

Commit 4b953fa

Browse files
authored
Merge branch 'main' into krylov-integration
2 parents bc8229a + c0a35e8 commit 4b953fa

39 files changed

+1249
-280
lines changed

.buildkite/pipeline.yml

+36
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,42 @@ steps:
649649
limit: 1
650650
depends_on: "init_cpu"
651651

652+
#####
653+
##### Vertical Coordinates tests
654+
#####
655+
656+
- label: "🥑 gpu vertical coordinate"
657+
env:
658+
JULIA_DEPOT_PATH: "$SVERDRUP_HOME/.julia-$BUILDKITE_BUILD_NUMBER"
659+
TEST_GROUP: "vertical_coordinate"
660+
GPU_TEST: "true"
661+
commands:
662+
- "$SVERDRUP_HOME/julia-$JULIA_VERSION/bin/julia -O0 --color=yes --project -e 'using Pkg; Pkg.test()'"
663+
agents:
664+
queue: Oceananigans
665+
architecture: GPU
666+
retry:
667+
automatic:
668+
- exit_status: 1
669+
limit: 1
670+
depends_on: "init_gpu"
671+
672+
- label: "🥒 cpu vertical coordinate"
673+
env:
674+
JULIA_DEPOT_PATH: "$TARTARUS_HOME/.julia-$BUILDKITE_BUILD_NUMBER"
675+
TEST_GROUP: "vertical_coordinate"
676+
CUDA_VISIBLE_DEVICES: "-1"
677+
commands:
678+
- "$TARTARUS_HOME/julia-$JULIA_VERSION/bin/julia -O0 --color=yes --project -e 'using Pkg; Pkg.test()'"
679+
agents:
680+
queue: Oceananigans
681+
architecture: CPU
682+
retry:
683+
automatic:
684+
- exit_status: 1
685+
limit: 1
686+
depends_on: "init_cpu"
687+
652688
#####
653689
##### Enzyme extension tests
654690
#####

Project.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Oceananigans"
22
uuid = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09"
33
authors = ["Climate Modeling Alliance and contributors"]
4-
version = "0.95.6"
4+
version = "0.95.7"
55

66
[deps]
77
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
@@ -65,8 +65,8 @@ Krylov = "0.9.9"
6565
LinearAlgebra = "1.9"
6666
Logging = "1.9"
6767
MPI = "0.16, 0.17, 0.18, 0.19, 0.20"
68-
Makie = "0.21"
69-
MakieCore = "0.7, 0.8"
68+
Makie = "0.21, 0.22"
69+
MakieCore = "0.7, 0.8, 0.9"
7070
NCDatasets = "0.12.10, 0.13.1, 0.14"
7171
OffsetArrays = "1.4"
7272
OrderedCollections = "1.1"

src/Advection/Advection.jl

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ using Oceananigans.Grids: with_halo
3434
using Oceananigans.Architectures: architecture, CPU
3535

3636
using Oceananigans.Operators
37+
using Oceananigans.Operators: flux_div_xyᶜᶜᶜ, Γᶠᶠᶜ, ∂t_σ
3738

3839
import Base: show, summary
3940
import Oceananigans.Grids: required_halo_size_x, required_halo_size_y, required_halo_size_z

src/Advection/vector_invariant_advection.jl

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
using Oceananigans.Operators
2-
using Oceananigans.Operators: flux_div_xyᶜᶜᶜ, Γᶠᶠᶜ
3-
41
# These are also used in Coriolis/hydrostatic_spherical_coriolis.jl
52
struct EnergyConserving{FT} <: AbstractAdvectionScheme{1, FT} end
63
struct EnstrophyConserving{FT} <: AbstractAdvectionScheme{1, FT} end
@@ -168,7 +165,7 @@ Base.show(io::IO, a::VectorInvariant{N, FT}) where {N, FT} =
168165
##### Convenience for WENO Vector Invariant
169166
#####
170167

171-
nothing_to_default(user_value; default) = isnothing(user_value) ? default : user_value
168+
nothing_to_default(user_value; default = nothing) = isnothing(user_value) ? default : user_value
172169

173170
"""
174171
WENOVectorInvariant(FT = Float64;
@@ -221,14 +218,14 @@ function WENOVectorInvariant(FT::DataType = Float64;
221218
default_upwinding = OnlySelfUpwinding(cross_scheme = divergence_scheme)
222219
upwinding = nothing_to_default(upwinding; default = default_upwinding)
223220

224-
N = max(required_halo_size_x(vorticity_scheme),
225-
required_halo_size_y(vorticity_scheme),
226-
required_halo_size_x(divergence_scheme),
227-
required_halo_size_y(divergence_scheme),
228-
required_halo_size_x(kinetic_energy_gradient_scheme),
229-
required_halo_size_y(kinetic_energy_gradient_scheme),
230-
required_halo_size_z(vertical_scheme))
221+
schemes = (vorticity_scheme, vertical_scheme, kinetic_energy_gradient_scheme, divergence_scheme)
222+
223+
NX = maximum(required_halo_size_x(s) for s in schemes)
224+
NY = maximum(required_halo_size_y(s) for s in schemes)
225+
NZ = maximum(required_halo_size_z(s) for s in schemes)
231226

227+
N = max(NX, NY, NZ)
228+
232229
FT = eltype(vorticity_scheme) # assumption
233230

234231
return VectorInvariant{N, FT, multi_dimensional_stencil}(vorticity_scheme,

src/Advection/vector_invariant_cross_upwinding.jl

+22-4
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,38 @@
1717
##### Cross and Self Upwinding of the Divergence flux
1818
#####
1919

20+
# If the grid is moving, the discrete continuity equation is calculated as:
21+
#
22+
# ωᵏ⁺¹ - ωᵏ δx(Ax u) + δy(Ay v) Δrᶜᶜᶜ ∂t_σ
23+
# ---------- = - --------------------- - -------------
24+
# Δzᶜᶜᶜ Vᶜᶜᶜ Δzᶜᶜᶜ
25+
#
26+
# Where ω is the vertical velocity with respect to a moving grid.
27+
# We upwind the discrete divergence `δx(Ax u) + δy(Ay v)` and then divide by the volume,
28+
# therefore, the correct term to be added to the divergence transport due to the moving grid is:
29+
#
30+
# Azᶜᶜᶜ Δrᶜᶜᶜ ∂t_σ
31+
#
32+
# which represents the static volume times the time derivative of the vertical grid scaling.
33+
# If the grid is stationary, ∂t_σ evaluates to zero, so this term disappears from the divergence flux.
34+
@inline Az_Δr_∂t_σ(i, j, k, grid) = Azᶜᶜᶜ(i, j, k, grid) * Δrᶜᶜᶜ(i, j, k, grid) * ∂t_σ(i, j, k, grid)
35+
2036
@inline function upwinded_divergence_flux_Uᶠᶜᶜ(i, j, k, grid, scheme::VectorInvariantCrossVerticalUpwinding, u, v)
2137
@inbounds= u[i, j, k]
2238
δ_stencil = scheme.upwinding.divergence_stencil
2339

24-
δᴿ = _biased_interpolate_xᶠᵃᵃ(i, j, k, grid, scheme, scheme.divergence_scheme, bias(û), flux_div_xyᶜᶜᶜ, δ_stencil, u, v)
40+
δᴿ = _biased_interpolate_xᶠᵃᵃ(i, j, k, grid, scheme, scheme.divergence_scheme, bias(û), flux_div_xyᶜᶜᶜ, δ_stencil, u, v)
41+
∂t_σ = _symmetric_interpolate_xᶠᵃᵃ(i, j, k, grid, scheme, cross_scheme, Az_Δr_∂t_σ)
2542

26-
return* δᴿ
43+
return* (δᴿ + ∂t_σ) # For static grids, ∂t_σ == 0
2744
end
2845

2946
@inline function upwinded_divergence_flux_Vᶜᶠᶜ(i, j, k, grid, scheme::VectorInvariantCrossVerticalUpwinding, u, v)
3047
@inbounds= v[i, j, k]
3148
δ_stencil = scheme.upwinding.divergence_stencil
3249

33-
δᴿ = _biased_interpolate_yᵃᶠᵃ(i, j, k, grid, scheme, scheme.divergence_scheme, bias(v̂), flux_div_xyᶜᶜᶜ, δ_stencil, u, v)
50+
δᴿ = _biased_interpolate_yᵃᶠᵃ(i, j, k, grid, scheme, scheme.divergence_scheme, bias(v̂), flux_div_xyᶜᶜᶜ, δ_stencil, u, v)
51+
∂t_σ = _symmetric_interpolate_yᵃᶠᵃ(i, j, k, grid, scheme, cross_scheme, Az_Δr_∂t_σ)
3452

35-
return* δᴿ
53+
return* (δᴿ + ∂t_σ) # For static grids, ∂t_σ == 0
3654
end

src/Advection/vector_invariant_self_upwinding.jl

+10-5
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,28 @@
22
##### Self Upwinding of Divergence Flux, the best option!
33
#####
44

5-
@inline δx_U(i, j, k, grid, u, v) = δxᶜᵃᵃ(i, j, k, grid, Ax_qᶠᶜᶜ, u)
6-
@inline δy_V(i, j, k, grid, u, v) = δyᵃᶜᵃ(i, j, k, grid, Ay_qᶜᶠᶜ, v)
5+
@inline δx_U(i, j, k, grid, u, v) = δxᶜᶜᶜ(i, j, k, grid, Ax_qᶠᶜᶜ, u)
6+
@inline δy_V(i, j, k, grid, u, v) = δyᶜᶜᶜ(i, j, k, grid, Ay_qᶜᶠᶜ, v)
7+
8+
# For moving grids, we include the time-derivative of the grid scaling in the divergence flux.
9+
# If the grid is stationary, `Az_Δr_∂t_σ` evaluates to zero.
10+
@inline δx_U_plus_∂t_σ(i, j, k, grid, u, v) = δxᶜᶜᶜ(i, j, k, grid, Ax_qᶠᶜᶜ, u) + Az_Δr_∂t_σ(i, j, k, grid)
11+
@inline δy_V_plus_∂t_σ(i, j, k, grid, u, v) = δyᶜᶜᶜ(i, j, k, grid, Ay_qᶜᶠᶜ, v) + Az_Δr_∂t_σ(i, j, k, grid)
712

813
# Velocity smoothness for divergence upwinding
914
@inline U_smoothness(i, j, k, grid, u, v) = ℑxᶜᵃᵃ(i, j, k, grid, Ax_qᶠᶜᶜ, u)
1015
@inline V_smoothness(i, j, k, grid, u, v) = ℑyᵃᶜᵃ(i, j, k, grid, Ay_qᶜᶠᶜ, v)
1116

1217
# Divergence smoothness for divergence upwinding
13-
@inline divergence_smoothness(i, j, k, grid, u, v) = δx_U(i, j, k, grid, u, v) + δy_V(i, j, k, grid, u, v)
18+
@inline divergence_smoothness(i, j, k, grid, u, v) = δx_U(i, j, k, grid, u, v) + δy_V(i, j, k, grid, u, v)
1419

1520
@inline function upwinded_divergence_flux_Uᶠᶜᶜ(i, j, k, grid, scheme::VectorInvariantSelfVerticalUpwinding, u, v)
1621

1722
δU_stencil = scheme.upwinding.δU_stencil
1823
cross_scheme = scheme.upwinding.cross_scheme
1924

2025
@inbounds= u[i, j, k]
21-
δvˢ = _symmetric_interpolate_xᶠᵃᵃ(i, j, k, grid, scheme, cross_scheme, δy_V, u, v)
26+
δvˢ = _symmetric_interpolate_xᶠᵃᵃ(i, j, k, grid, scheme, cross_scheme, δy_V_plus_∂t_σ, u, v)
2227
δuᴿ = _biased_interpolate_xᶠᵃᵃ(i, j, k, grid, scheme, scheme.divergence_scheme, bias(û), δx_U, δU_stencil, u, v)
2328

2429
return* (δvˢ + δuᴿ)
@@ -30,7 +35,7 @@ end
3035
cross_scheme = scheme.upwinding.cross_scheme
3136

3237
@inbounds= v[i, j, k]
33-
δuˢ = _symmetric_interpolate_yᵃᶠᵃ(i, j, k, grid, scheme, cross_scheme, δx_U, u, v)
38+
δuˢ = _symmetric_interpolate_yᵃᶠᵃ(i, j, k, grid, scheme, cross_scheme, δx_U_plus_∂t_σ, u, v)
3439
δvᴿ = _biased_interpolate_yᵃᶠᵃ(i, j, k, grid, scheme, scheme.divergence_scheme, bias(v̂), δy_V, δV_stencil, u, v)
3540

3641
return* (δuˢ + δvᴿ)

src/Grids/Grids.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export XRegularRG, YRegularRG, ZRegularRG, XYRegularRG, XYZRegularRG
1111
export LatitudeLongitudeGrid, XRegularLLG, YRegularLLG, ZRegularLLG
1212
export OrthogonalSphericalShellGrid, ConformalCubedSphereGrid, ZRegOrthogonalSphericalShellGrid
1313
export conformal_cubed_sphere_panel
14+
export MutableVerticalDiscretization
1415
export node, nodes
1516
export ξnode, ηnode, rnode
1617
export xnode, ynode, znode, λnode, φnode
@@ -19,6 +20,7 @@ export spacings
1920
export xspacings, yspacings, zspacings, λspacings, φspacings, rspacings
2021
export minimum_xspacing, minimum_yspacing, minimum_zspacing
2122
export static_column_depthᶜᶜᵃ, static_column_depthᶠᶜᵃ, static_column_depthᶜᶠᵃ, static_column_depthᶠᶠᵃ
23+
export column_depthᶜᶜᵃ, column_depthᶠᶜᵃ, column_depthᶜᶠᵃ, column_depthᶠᶠᵃ
2224
export offset_data, new_data
2325
export on_architecture
2426

@@ -118,7 +120,7 @@ struct ZDirection <: AbstractDirection end
118120
struct NegativeZDirection <: AbstractDirection end
119121

120122
include("abstract_grid.jl")
121-
include("vertical_coordinates.jl")
123+
include("vertical_discretization.jl")
122124
include("grid_utils.jl")
123125
include("nodes_and_spacings.jl")
124126
include("zeros_and_ones.jl")

src/Grids/grid_generation.jl

+51-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ function generate_coordinate(FT, topo::AT, N, H, node_generator, coordinate_name
8888
C = OffsetArray(on_architecture(arch, C.parent), C.offsets...)
8989

9090
if coordinate_name == :z
91-
return L, StaticVerticalCoordinate(F, C, Δᶠ, Δᶜ)
91+
return L, StaticVerticalDiscretization(F, C, Δᶠ, Δᶜ)
9292
else
9393
return L, F, C, Δᶠ, Δᶜ
9494
end
@@ -125,7 +125,7 @@ function generate_coordinate(FT, topo::AT, N, H, node_interval::Tuple{<:Number,
125125
C = OffsetArray(C, -H)
126126

127127
if coordinate_name == :z
128-
return FT(L), StaticVerticalCoordinate(F, C, FT(Δᶠ), FT(Δᶜ))
128+
return FT(L), StaticVerticalDiscretization(F, C, FT(Δᶠ), FT(Δᶜ))
129129
else
130130
return FT(L), F, C, FT(Δᶠ), FT(Δᶜ)
131131
end
@@ -134,7 +134,7 @@ end
134134
# Flat domains
135135
function generate_coordinate(FT, ::Flat, N, H, c::Number, coordinate_name, arch)
136136
if coordinate_name == :z
137-
return FT(1), StaticVerticalCoordinate(range(FT(c), FT(c), length=N), range(FT(c), FT(c), length=N), FT(1), FT(1))
137+
return FT(1), StaticVerticalDiscretization(range(FT(c), FT(c), length=N), range(FT(c), FT(c), length=N), FT(1), FT(1))
138138
else
139139
return FT(1), range(FT(c), FT(c), length=N), range(FT(c), FT(c), length=N), FT(1), FT(1)
140140
end
@@ -145,8 +145,55 @@ end
145145
# FT(1), c, c, FT(1), FT(1)
146146
function generate_coordinate(FT, ::Flat, N, H, ::Nothing, coordinate_name, arch)
147147
if coordinate_name == :z
148-
return FT(1), StaticVerticalCoordinate(nothing, nothing, FT(1), FT(1))
148+
return FT(1), StaticVerticalDiscretization(nothing, nothing, FT(1), FT(1))
149149
else
150150
return FT(1), nothing, nothing, FT(1), FT(1)
151151
end
152152
end
153+
154+
#####
155+
##### MutableVerticalDiscretization
156+
#####
157+
158+
generate_coordinate(FT, ::Periodic, N, H, ::MutableVerticalDiscretization, coordinate_name, arch, args...) =
159+
throw(ArgumentError("Periodic domains are not supported for MutableVerticalDiscretization"))
160+
161+
# Generate a vertical coordinate with a scaling (`σ`) with respect to a reference coordinate `r` with spacing `Δr`.
162+
# The grid might move with time, so the coordinate includes the time-derivative of the scaling `∂t_σ`.
163+
# The value of the vertical coordinate at `Nz+1` is saved in `ηⁿ`.
164+
function generate_coordinate(FT, topo, size, halo, coordinate::MutableVerticalDiscretization, coordinate_name, dim::Int, arch)
165+
166+
Nx, Ny, Nz = size
167+
Hx, Hy, Hz = halo
168+
169+
if dim != 3
170+
msg = "MutableVerticalDiscretization is supported only in the third dimension (z)"
171+
throw(ArgumentError(msg))
172+
end
173+
174+
if coordinate_name != :z
175+
msg = "MutableVerticalDiscretization is supported only for the z-coordinate"
176+
throw(ArgumentError(msg))
177+
end
178+
179+
r_faces = coordinate.cᵃᵃᶠ
180+
181+
Lr, rᵃᵃᶠ, rᵃᵃᶜ, Δrᵃᵃᶠ, Δrᵃᵃᶜ = generate_coordinate(FT, topo[3](), Nz, Hz, r_faces, :r, arch)
182+
183+
args = (topo, (Nx, Ny, Nz), (Hx, Hy, Hz))
184+
185+
σᶜᶜ⁻ = new_data(FT, arch, (Center, Center, Nothing), args...)
186+
σᶜᶜⁿ = new_data(FT, arch, (Center, Center, Nothing), args...)
187+
σᶠᶜⁿ = new_data(FT, arch, (Face, Center, Nothing), args...)
188+
σᶜᶠⁿ = new_data(FT, arch, (Center, Face, Nothing), args...)
189+
σᶠᶠⁿ = new_data(FT, arch, (Face, Face, Nothing), args...)
190+
ηⁿ = new_data(FT, arch, (Center, Center, Nothing), args...)
191+
∂t_σ = new_data(FT, arch, (Center, Center, Nothing), args...)
192+
193+
# Fill all the scalings with one for now (i.e. z == r)
194+
for σ in (σᶜᶜ⁻, σᶜᶜⁿ, σᶠᶜⁿ, σᶜᶠⁿ, σᶠᶠⁿ)
195+
fill!(σ, 1)
196+
end
197+
198+
return Lr, MutableVerticalDiscretization(rᵃᵃᶠ, rᵃᵃᶜ, Δrᵃᵃᶠ, Δrᵃᵃᶜ, ηⁿ, σᶜᶜⁿ, σᶠᶜⁿ, σᶜᶠⁿ, σᶠᶠⁿ, σᶜᶜ⁻, ∂t_σ)
199+
end

src/Grids/grid_utils.jl

+8-2
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ end
299299
function dimension_summary(topo, name, dom, z::AbstractVerticalCoordinate, pad_domain=0)
300300
prefix = domain_summary(topo, name, dom)
301301
padding = " "^(pad_domain+1)
302-
return string(prefix, padding, coordinate_summary(topo, z.Δᵃᵃᶜ, name))
302+
return string(prefix, padding, coordinate_summary(topo, z, name))
303303
end
304304

305305
function dimension_summary(topo, name, dom, spacing, pad_domain=0)
@@ -317,14 +317,20 @@ coordinate_summary(topo, Δ::Union{AbstractVector, AbstractMatrix}, name) =
317317
name, prettysummary(maximum(parent(Δ))))
318318

319319
#####
320-
##### Static column depths
320+
##### Static and Dynamic column depths
321321
#####
322322

323323
@inline static_column_depthᶜᶜᵃ(i, j, grid) = grid.Lz
324324
@inline static_column_depthᶜᶠᵃ(i, j, grid) = grid.Lz
325325
@inline static_column_depthᶠᶜᵃ(i, j, grid) = grid.Lz
326326
@inline static_column_depthᶠᶠᵃ(i, j, grid) = grid.Lz
327327

328+
# Will be extended in the `ImmersedBoundaries` module for a ``mutable'' grid type
329+
@inline column_depthᶜᶜᵃ(i, j, k, grid, η) = static_column_depthᶜᶜᵃ(i, j, grid)
330+
@inline column_depthᶠᶜᵃ(i, j, k, grid, η) = static_column_depthᶠᶜᵃ(i, j, grid)
331+
@inline column_depthᶜᶠᵃ(i, j, k, grid, η) = static_column_depthᶜᶠᵃ(i, j, grid)
332+
@inline column_depthᶠᶠᵃ(i, j, k, grid, η) = static_column_depthᶠᶠᵃ(i, j, grid)
333+
328334
#####
329335
##### Spherical geometry
330336
#####

0 commit comments

Comments
 (0)