Skip to content

Commit fb7fb70

Browse files
authored
Grids now have a topology (#614)
Grids now have a topology
2 parents 11c41e1 + 3bef9da commit fb7fb70

25 files changed

+123
-94
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Oceananigans"
22
uuid = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09"
3-
version = "0.20.0"
3+
version = "0.21.0"
44

55
[deps]
66
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"

src/AbstractOperations/AbstractOperations.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ using Oceananigans.Fields
1818
using Oceananigans.Operators
1919
using Oceananigans.BoundaryConditions
2020

21-
using Oceananigans: AbstractGrid
2221
using Oceananigans.Architectures: device
2322
using Oceananigans.Models: AbstractModel
2423
using Oceananigans.Diagnostics: HorizontalAverage, normalize_horizontal_sum!

src/AbstractOperations/binary_operations.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ end
3939
"""Return an expression that defines an abstract `BinaryOperator` named `op` for `AbstractLocatedField`."""
4040
function define_binary_operator(op)
4141
return quote
42-
import Oceananigans: AbstractGrid
42+
import Oceananigans.Grids: AbstractGrid
4343
import Oceananigans.Fields: AbstractLocatedField
4444

4545
local location = Oceananigans.Fields.location

src/AbstractOperations/unary_operations.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ macro unary(ops...)
7373

7474
for op in ops
7575
define_unary_operator = quote
76-
import Oceananigans: AbstractGrid
76+
import Oceananigans.Grids: AbstractGrid
7777
import Oceananigans.Fields: AbstractLocatedField
7878

7979
local location = Oceananigans.Fields.location

src/BoundaryConditions/BoundaryConditions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module BoundaryConditions
22

33
export
4-
BCType, Periodic, Flux, Gradient, Value, NoPenetration,
4+
BCType, Flux, Gradient, Value, NoPenetration,
55
BoundaryCondition, bctype, getbc, setbc!,
66
CoordinateBoundaryConditions,
77
FieldBoundaryConditions, HorizontallyPeriodicBCs, ChannelBCs,

src/Buoyancy/Buoyancy.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ export
55
LinearEquationOfState, RoquetIdealizedNonlinearEquationOfState,
66
∂x_b, ∂y_b, ∂z_b, buoyancy_perturbation, buoyancy_frequency_squared
77

8-
using
9-
Printf,
10-
Oceananigans.Operators
11-
12-
using Oceananigans: AbstractGrid
8+
using Printf
9+
using Oceananigans.Grids
10+
using Oceananigans.Operators
1311

1412
# Physical constants
1513
# https://en.wikipedia.org/wiki/Gravitational_acceleration#Gravity_model_for_Earth (30 Oct 2019)

src/Coriolis/Coriolis.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ export
44
FPlane, NonTraditionalFPlane, BetaPlane,
55
x_f_cross_U, y_f_cross_U, z_f_cross_U
66

7+
using Printf
8+
using Oceananigans.Grids
9+
using Oceananigans.Operators
10+
711
# Physical constants for FPlane and BetaPlane constructors.
812
const Ω_Earth = 7.292115e-5 # [s⁻¹] https://en.wikipedia.org/wiki/Earth%27s_rotation#Angular_speed
913
const R_Earth = 6371.0e3 # Mean radius of the Earth [m] https://en.wikipedia.org/wiki/Earth

src/Coriolis/beta_plane.jl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
using Printf
2-
using Oceananigans.Operators
3-
4-
using Oceananigans: AbstractGrid
5-
61
"""
72
BetaPlane{T} <: AbstractRotation
83

src/Coriolis/f_plane.jl

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
using Printf
2-
using Oceananigans.Operators
3-
4-
using Oceananigans: AbstractGrid
5-
61
"""
72
FPlane{FT} <: AbstractRotation
83

src/Coriolis/no_rotation.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using Oceananigans: AbstractGrid
2-
31
#####
42
##### Functions for non-rotating models
53
#####

src/Diagnostics/horizontal_average.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ model and you want to save the output to disk by passing it to an output writer.
3737
"""
3838
function HorizontalAverage(field; frequency=nothing, interval=nothing, return_type=Array)
3939
arch = architecture(field)
40-
result = zeros(arch, field.grid, 1, 1, field.grid.Tz)
40+
result = zeros(arch, field.grid, 1, 1, field.grid.Nz + 2field.grid.Hz)
4141
return HorizontalAverage(field, result, frequency, interval, 0.0, return_type, field.grid)
4242
end
4343

src/Fields/field.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ using OffsetArrays
77
import Oceananigans.Architectures: architecture
88
import Oceananigans.Utils: datatuple
99

10-
using Oceananigans: AbstractGrid
11-
using Oceananigans.Architectures: @hascuda, CPU, GPU
10+
using Oceananigans.Architectures
11+
using Oceananigans.Grids
12+
using Oceananigans.Utils
1213

1314
@hascuda using CuArrays
1415

@@ -197,12 +198,12 @@ function OffsetArray(underlying_data, grid)
197198
end
198199

199200
function Base.zeros(T, ::CPU, grid)
200-
underlying_data = zeros(T, grid.Tx, grid.Ty, grid.Tz)
201+
underlying_data = zeros(T, grid.Nx + 2grid.Hx, grid.Ny + 2grid.Hy, grid.Nz + 2grid.Hz)
201202
return OffsetArray(underlying_data, grid)
202203
end
203204

204205
function Base.zeros(T, ::GPU, grid)
205-
underlying_data = CuArray{T}(undef, grid.Tx, grid.Ty, grid.Tz)
206+
underlying_data = CuArray{T}(undef, grid.Nx + 2grid.Hx, grid.Ny + 2grid.Hy, grid.Nz + 2grid.Hz)
206207
underlying_data .= 0 # Gotta do this otherwise you might end up with a few NaN values!
207208
return OffsetArray(underlying_data, grid)
208209
end

src/Grids/Grids.jl

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,56 @@
11
module Grids
22

3-
export RegularCartesianGrid, VerticallyStretchedCartesianGrid
3+
export
4+
AbstractTopology, Periodic, Bounded, Flat, topology,
5+
AbstractGrid, RegularCartesianGrid, VerticallyStretchedCartesianGrid
6+
7+
import Base: size, length, eltype, show
48

59
using Oceananigans
610

11+
"""
12+
AbstractTopology
13+
14+
Abstract supertype for grid topologies.
15+
"""
16+
abstract type AbstractTopology end
17+
18+
"""
19+
Periodic
20+
21+
Grid topology for periodic dimensions.
22+
"""
23+
struct Periodic <: AbstractTopology end
24+
25+
"""
26+
Bounded
27+
28+
Grid topology for bounded dimensions. These could be wall-bounded dimensions
29+
or dimensions
30+
"""
31+
struct Bounded <: AbstractTopology end
32+
33+
"""
34+
Flat
35+
36+
Grid topology for flat dimensions, generally with one grid point, along which the solution
37+
is uniform and does not vary.
38+
"""
39+
struct Flat <: AbstractTopology end
40+
41+
"""
42+
AbstractGrid{FT, TX, TY, TZ}
43+
44+
Abstract supertype for grids with elements of type `FT` and topology `{TX, TY, TZ}`.
45+
"""
46+
abstract type AbstractGrid{FT, TX, TY, TZ} end
47+
48+
eltype(::AbstractGrid{FT}) where FT = FT
49+
topology(::AbstractGrid{FT, TX, TY, TZ}) where {FT, TX, TY, TZ} = (TX, TY, TZ)
50+
51+
size(grid::AbstractGrid) = (grid.Nx, grid.Ny, grid.Nz)
52+
length(grid::AbstractGrid) = (grid.Lx, grid.Ly, grid.Lz)
53+
754
include("grid_utils.jl")
855
include("regular_cartesian_grid.jl")
956
include("vertically_stretched_cartesian_grid.jl")

src/Grids/grid_utils.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@ unpack_grid(grid) = grid.Nx, grid.Ny, grid.Nz, grid.Lx, grid.Ly, grid.Lz
88
##### Input validation
99
#####
1010

11+
instantiate_datatype(t::DataType) = t()
12+
instantiate_datatype(t) = t
13+
14+
function validate_topology(topology)
15+
TX, TY, TZ = topology
16+
TX = instantiate_datatype(TX)
17+
TY = instantiate_datatype(TY)
18+
TZ = instantiate_datatype(TZ)
19+
20+
for t in (TX, TY, TZ)
21+
if !isa(t, AbstractTopology)
22+
e = "$(typeof(t)) is not a valid topology! " *
23+
"Valid topologies are: Periodic, Bounded, Flat."
24+
throw(ArgumentError(e))
25+
end
26+
end
27+
28+
return TX, TY, TZ
29+
end
30+
1131
"""Validate that an argument tuple is the right length and has elements of type `argtype`."""
1232
function validate_tupled_argument(arg, argtype, argname)
1333
length(arg) == 3 || throw(ArgumentError("length($argname) must be 3."))

src/Grids/regular_cartesian_grid.jl

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
import Base: size, length, eltype, show
2-
3-
using Oceananigans: AbstractGrid
4-
51
"""
6-
RegularCartesianGrid{FT<:AbstractFloat, R<:AbstractRange} <: AbstractGrid{FT}
2+
RegularCartesianGrid{FT, TX, TY, TZ, R} <: AbstractGrid{FT, TX, TY, TZ}
73
84
A Cartesian grid with with constant grid spacings `Δx`, `Δy`, and `Δz` between cell centers
9-
and cell faces.
5+
and cell faces, elements of type `FT`, topology `{TX, TY, TZ}`, and coordinate ranges
6+
of type `R`.
107
"""
11-
struct RegularCartesianGrid{FT<:AbstractFloat, R<:AbstractRange} <: AbstractGrid{FT}
8+
struct RegularCartesianGrid{FT, TX, TY, TZ, R} <: AbstractGrid{FT, TX, TY, TZ}
129
# Number of grid points in (x,y,z).
1310
Nx::Int
1411
Ny::Int
@@ -17,10 +14,6 @@ struct RegularCartesianGrid{FT<:AbstractFloat, R<:AbstractRange} <: AbstractGrid
1714
Hx::Int
1815
Hy::Int
1916
Hz::Int
20-
# Total number of grid points (including halo regions).
21-
Tx::Int
22-
Ty::Int
23-
Tz::Int
2417
# Domain size [m].
2518
Lx::FT
2619
Ly::FT
@@ -41,7 +34,8 @@ struct RegularCartesianGrid{FT<:AbstractFloat, R<:AbstractRange} <: AbstractGrid
4134
end
4235

4336
"""
44-
RegularCartesianGrid([FT=Float64]; size, length, x, y, z)
37+
RegularCartesianGrid([FT=Float64]; size, length, topology=(Periodic, Periodic, Bounded),
38+
x=nothing, y=nothing, z=nothing)
4539
4640
Creates a `RegularCartesianGrid` with `size = (Nx, Ny, Nz)` grid points.
4741
@@ -50,6 +44,10 @@ indicating the left and right endpoints of each dimensions, e.g. `x=(-π, π)` o
5044
the `length` argument, e.g. `length=(Lx, Ly, Lz)` which specifies the length of each dimension
5145
in which case 0 ≤ x ≤ Lx, 0 ≤ y ≤ Ly, and -Lz ≤ z ≤ 0.
5246
47+
A grid topology may be specified via a tuple assigning one of `Periodic`, `Bounded, and `Flat`
48+
to each dimension. By default, a horizontally periodic grid topology `(Periodic, Periodic, Flat)`
49+
is assumed.
50+
5351
Constants are stored using floating point values of type `FT`. By default this is `Float64`.
5452
Make sure to specify the desired `FT` if not using `Float64`.
5553
@@ -79,23 +77,20 @@ domain: x ∈ [0.0, 8.0], y ∈ [-10.0, 10.0], z ∈ [3.141592653589793, -3.1415
7977
grid spacing (Δx, Δy, Δz) = (0.25f0, 0.625f0, 0.3926991f0)
8078
```
8179
"""
82-
function RegularCartesianGrid(FT=Float64; size, halo=(1, 1, 1),
80+
function RegularCartesianGrid(FT=Float64; size, halo=(1, 1, 1), topology=(Periodic, Periodic, Bounded),
8381
length=nothing, x=nothing, y=nothing, z=nothing)
8482

8583
# Hack that allows us to use `size` and `length` as keyword arguments but then also
8684
# use the `length` function.
8785
sz, len = size, length
8886
length = Base.length
8987

88+
TX, TY, TZ = validate_topology(topology)
9089
Lx, Ly, Lz, x, y, z = validate_grid_size_and_length(sz, len, halo, x, y, z)
9190

9291
Nx, Ny, Nz = sz
9392
Hx, Hy, Hz = halo
9493

95-
Tx = Nx + 2Hx
96-
Ty = Ny + 2Hy
97-
Tz = Nz + 2Hz
98-
9994
Δx = convert(FT, Lx / Nx)
10095
Δy = convert(FT, Ly / Ny)
10196
Δz = convert(FT, Lz / Nz)
@@ -112,23 +107,19 @@ function RegularCartesianGrid(FT=Float64; size, halo=(1, 1, 1),
112107
yF = range(y₁, y₂; length=Ny+1)
113108
zF = range(z₁, z₂; length=Nz+1)
114109

115-
RegularCartesianGrid{FT, typeof(xC)}(Nx, Ny, Nz, Hx, Hy, Hz, Tx, Ty, Tz,
116-
Lx, Ly, Lz, Δx, Δy, Δz, xC, yC, zC, xF, yF, zF)
110+
RegularCartesianGrid{FT, typeof(TX), typeof(TY), typeof(TZ), typeof(xC)}(
111+
Nx, Ny, Nz, Hx, Hy, Hz, Lx, Ly, Lz, Δx, Δy, Δz, xC, yC, zC, xF, yF, zF)
117112
end
118113

119-
size(grid::RegularCartesianGrid) = (grid.Nx, grid.Ny, grid.Nz)
120-
length(grid::RegularCartesianGrid) = (grid.Lx, grid.Ly, grid.Lz)
121-
eltype(grid::RegularCartesianGrid{FT}) where FT = FT
122-
123-
short_show(grid::RegularCartesianGrid{T}) where T =
124-
"RegularCartesianGrid{$T}(Nx=$(grid.Nx), Ny=$(grid.Ny), Nz=$(grid.Nz))"
114+
short_show(grid::RegularCartesianGrid{FT, TX, TY, TZ}) where {FT, TX, TY, TZ} =
115+
"RegularCartesianGrid{$FT, $TX, $TY, $TZ}(Nx=$(grid.Nx), Ny=$(grid.Ny), Nz=$(grid.Nz))"
125116

126117
show_domain(grid) = string("x ∈ [", grid.xF[1], ", ", grid.xF[end], "], ",
127118
"y ∈ [", grid.yF[1], ", ", grid.yF[end], "], ",
128119
"z ∈ [", grid.zF[1], ", ", grid.zF[end], "]")
129120

130-
show(io::IO, g::RegularCartesianGrid) =
131-
print(io, "RegularCartesianGrid{$(eltype(g))}\n",
121+
show(io::IO, g::RegularCartesianGrid{FT, TX, TY, TZ}) where {FT, TX, TY, TZ} =
122+
print(io, "RegularCartesianGrid{$FT, $TX, $TY, $TZ}\n",
132123
"domain: x ∈ [$(g.xF[1]), $(g.xF[end])], y ∈ [$(g.yF[1]), $(g.yF[end])], z ∈ [$(g.zF[1]), $(g.zF[end])]", '\n',
133124
" resolution (Nx, Ny, Nz) = ", (g.Nx, g.Ny, g.Nz), '\n',
134125
" halo size (Hx, Hy, Hz) = ", (g.Hx, g.Hy, g.Hz), '\n',

src/Grids/vertically_stretched_cartesian_grid.jl

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
import Base: size, length, eltype, show
2-
3-
using Oceananigans: AbstractGrid
4-
51
"""
6-
VerticallyStretchedCartesianGrid{FT<:AbstractFloat, R<:AbstractRange, A<:AbstractArray} <: AbstractGrid{FT}
2+
VerticallyStretchedCartesianGrid{FT, TX, TY, TZ, R, A} <: AbstractGrid{FT, TX, TY, TZ}
73
84
A Cartesian grid with with constant horizontal grid spacings `Δx` and `Δy`, and
9-
non-uniform or stretched vertical grid spacing `Δz` between cell centers and cell faces.
5+
non-uniform or stretched vertical grid spacing `Δz` between cell centers and cell faces,
6+
topology `{TX, TY, TZ}`, and coordinate ranges of type `R` (where a range can be used) and
7+
`A` (where an array is needed).
108
"""
11-
struct VerticallyStretchedCartesianGrid{FT<:AbstractFloat, R<:AbstractRange, A<:AbstractArray} <: AbstractGrid{FT}
9+
struct VerticallyStretchedCartesianGrid{FT, TX, TY, TZ, R, A} <: AbstractGrid{FT, TX, TY, TZ}
1210
# Number of grid points in (x,y,z).
1311
Nx::Int
1412
Ny::Int
@@ -17,10 +15,6 @@ struct VerticallyStretchedCartesianGrid{FT<:AbstractFloat, R<:AbstractRange, A<:
1715
Hx::Int
1816
Hy::Int
1917
Hz::Int
20-
# Total number of grid points (including halo regions).
21-
Tx::Int
22-
Ty::Int
23-
Tz::Int
2418
# Domain size [m].
2519
Lx::FT
2620
Ly::FT
@@ -42,22 +36,20 @@ struct VerticallyStretchedCartesianGrid{FT<:AbstractFloat, R<:AbstractRange, A<:
4236
end
4337

4438
function VerticallyStretchedCartesianGrid(FT=Float64, arch=CPU();
45-
size, halo=(1, 1, 1), length=nothing, x=nothing, y=nothing, z=nothing, zF=nothing)
39+
size, halo=(1, 1, 1), topology=(Periodic, Periodic, Bounded),
40+
length=nothing, x=nothing, y=nothing, z=nothing, zF=nothing)
4641

4742
# Hack that allows us to use `size` and `length` as keyword arguments but then also
4843
# use the `size` and `length` functions.
4944
sz, len = size, length
5045
length = Base.length
5146

47+
TX, TY, TZ = validate_topology(topology)
5248
Lx, Ly, Lz, x, y, z = validate_grid_size_and_length(sz, len, halo, x, y, z)
5349

5450
Nx, Ny, Nz = sz
5551
Hx, Hy, Hz = halo
5652

57-
Tx = Nx + 2*Hx
58-
Ty = Ny + 2*Hy
59-
Tz = Nz + 2*Hz
60-
6153
Δx = convert(FT, Lx / Nx)
6254
Δy = convert(FT, Ly / Ny)
6355

@@ -73,6 +65,6 @@ function VerticallyStretchedCartesianGrid(FT=Float64, arch=CPU();
7365

7466
zF, zC, ΔzF, ΔzC = validate_and_generate_variable_grid_spacing(FT, zF, Nz, z₁, z₂)
7567

76-
VerticallyStretchedCartesianGrid{FT, typeof(xF), typeof(zF)}(Nx, Ny, Nz, Hx, Hy, Hz, Tx, Ty, Tz, Lx, Ly, Lz,
77-
Δx, Δy, ΔzF, ΔzC, xC, yC, zC, xF, yF, zF)
68+
VerticallyStretchedCartesianGrid{FT, typeof(TX), typeof(TY), typeof(TZ), typeof(xF), typeof(zF)}(
69+
Nx, Ny, Nz, Hx, Hy, Hz, Lx, Ly, Lz, Δx, Δy, ΔzF, ΔzC, xC, yC, zC, xF, yF, zF)
7870
end

0 commit comments

Comments
 (0)