Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tripolar grid in Oceananigans (only serial) #3913

Open
wants to merge 56 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
0d97e99
add tripolar grid
simone-silvestri Nov 11, 2024
06c7a46
tripolar grid
simone-silvestri Nov 11, 2024
e045265
add the tests
simone-silvestri Nov 11, 2024
2b97a62
Update runtests.jl
navidcy Nov 11, 2024
d31586c
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Nov 11, 2024
dc4a327
Update test_tripolar_grid.jl
navidcy Nov 11, 2024
52ccb9f
fix imports
navidcy Nov 11, 2024
9cb40d2
make the code compile
simone-silvestri Nov 11, 2024
c556d43
Merge branch 'ss/tripolar-grid-in-oceananigans' of github.com:CliMA/O…
simone-silvestri Nov 11, 2024
6670cf8
fix other imports + change in docstring
simone-silvestri Nov 11, 2024
1d441bf
start exporting the TripolarGrid
simone-silvestri Nov 11, 2024
db49f4d
remove the tests from unit tests
simone-silvestri Nov 11, 2024
76fd28c
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
navidcy Nov 12, 2024
44f62c1
some imports
navidcy Nov 12, 2024
41b1d8c
use Distances.haversine
navidcy Nov 12, 2024
4e7fc13
fix Murray citation
navidcy Nov 12, 2024
55359b1
start with the fold
simone-silvestri Nov 12, 2024
da0caa5
Merge branch 'ss/tripolar-grid-in-oceananigans' of github.com:CliMA/O…
simone-silvestri Nov 12, 2024
67e6ef4
workaround
simone-silvestri Nov 12, 2024
cfc6524
the grid builds, onto the boundary conditions
simone-silvestri Nov 12, 2024
e2a7157
still some problems with the coordinates
simone-silvestri Nov 12, 2024
ce8c49e
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Nov 12, 2024
f4761db
try it like this
simone-silvestri Nov 12, 2024
8b98139
Merge branch 'ss/tripolar-grid-in-oceananigans' of github.com:CliMA/O…
simone-silvestri Nov 12, 2024
be9f37f
using OrthogonalSphericalShellGrids
simone-silvestri Nov 12, 2024
5947713
lets get this ready
simone-silvestri Nov 13, 2024
602dc4a
shuffle around stuff
simone-silvestri Nov 13, 2024
285ee12
add tests
simone-silvestri Nov 13, 2024
ef91201
CPU is not found?
simone-silvestri Nov 13, 2024
99eddf8
multiple archs in tests
simone-silvestri Nov 13, 2024
16a3101
allowscalar
simone-silvestri Nov 14, 2024
a75ab85
probably missing this using
simone-silvestri Nov 14, 2024
9d8c773
almost there?
simone-silvestri Nov 15, 2024
684109d
Merge remote-tracking branch 'origin/main' into ss/tripolar-grid-in-o…
simone-silvestri Nov 15, 2024
f690048
tests should pass
simone-silvestri Nov 15, 2024
a87225e
fix docs
simone-silvestri Nov 15, 2024
5a99938
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Nov 15, 2024
ed2fe2f
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Nov 18, 2024
ae4008b
add vector rotation tests
simone-silvestri Nov 21, 2024
dbf9143
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Dec 11, 2024
4c6c141
Merge remote-tracking branch 'origin/main' into ss/tripolar-grid-in-o…
simone-silvestri Feb 11, 2025
c48384f
revamp
simone-silvestri Feb 11, 2025
a3d34cc
Update Grids.jl
simone-silvestri Feb 11, 2025
4a5bd9c
Update OrthogonalSphericalShellGrids.jl
simone-silvestri Feb 11, 2025
575b3e1
Update OrthogonalSphericalShellGrids.jl
simone-silvestri Feb 11, 2025
52dd73c
bugfix
simone-silvestri Feb 11, 2025
d4fb180
convert to 0 360
simone-silvestri Feb 11, 2025
a4827af
fix all tests
simone-silvestri Feb 11, 2025
cbff3f2
return as before
simone-silvestri Feb 11, 2025
c4c7267
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Feb 12, 2025
f599f96
Update boundary_condition.jl
simone-silvestri Feb 12, 2025
b905cea
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Feb 13, 2025
0a4ff58
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Feb 15, 2025
69f46a0
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Feb 16, 2025
bf3de89
Update Oceananigans.jl
simone-silvestri Feb 16, 2025
fd40e48
Merge branch 'main' into ss/tripolar-grid-in-oceananigans
simone-silvestri Feb 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,25 @@ steps:
limit: 1
depends_on: "init_cpu"

#####
##### Tripolar Grid tests
#####

- label: "🦃 cpu tripolar grid tests"
env:
JULIA_DEPOT_PATH: "$TARTARUS_HOME/.julia-$BUILDKITE_BUILD_NUMBER"
TEST_GROUP: "tripolar_grid"
commands:
- "$TARTARUS_HOME/julia-$JULIA_VERSION/bin/julia -O0 --color=yes --project -e 'using Pkg; Pkg.test()'"
agents:
queue: Oceananigans
architecture: CPU
retry:
automatic:
- exit_status: 1
limit: 1
depends_on: "init_cpu"

#####
##### NonhydrostaticModel and time stepping (part 1)
#####
Expand Down
7 changes: 7 additions & 0 deletions docs/src/appendix/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ Modules = [Oceananigans.Grids]
Private = false
```

## OrthogonalSphericalShellGrids

```@autodocs
Modules = [Oceananigans.OrthogonalSphericalShellGrids]
Private = false
```

## Immersed boundaries

```@autodocs
Expand Down
2 changes: 1 addition & 1 deletion docs/src/grids.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ The shape of the physical domain determines what grid type should be used:
3. [`OrthogonalSphericalShellGrid`](@ref Oceananigans.Grids.OrthogonalSphericalShellGrid) represents sectors of thin spherical shells divided with mesh lines that intersect at right angles (thus, orthogonal) but are otherwise arbitrary.

!!! note "OrthogonalSphericalShellGrids.jl"
See the auxiliary package [`OrthogonalSphericalShellGrids.jl`](https://github.com/CliMA/OrthogonalSphericalShellGrids.jl)
See the auxiliary module [`OrthogonalSphericalShellGrids.jl`](@ref Oceananigans.OrthogonalSphericalShellGrids)
for recipes that implement some useful `OrthogonalSphericalShellGrid`, including the
["tripolar" grid](https://www.sciencedirect.com/science/article/abs/pii/S0021999196901369).

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

include("apply_flux_bcs.jl")

Expand Down
3 changes: 3 additions & 0 deletions src/BoundaryConditions/apply_flux_bcs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ end
@inline apply_z_top_bc!(Gc, loc, ::NotFluxBC, args...) = nothing
@inline apply_z_bottom_bc!(Gc, loc, ::NotFluxBC, args...) = nothing

# shortcut for the zipper BC
@inline apply_y_north_bc!(Gc, loc, ::ZBC, args...) = nothing

@inline flip(::Center) = Face()
@inline flip(::Face) = Center()

Expand Down
3 changes: 3 additions & 0 deletions src/BoundaryConditions/boundary_condition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,23 @@ const GBC = BoundaryCondition{<:Gradient}
const ZFBC = BoundaryCondition{Flux, Nothing} # "zero" flux
const MCBC = BoundaryCondition{<:MultiRegionCommunication}
const DCBC = BoundaryCondition{<:DistributedCommunication}
const ZBC = BoundaryCondition{<:Zipper}

# More readable BC constructors for the public API.
PeriodicBoundaryCondition() = BoundaryCondition(Periodic(), nothing)
NoFluxBoundaryCondition() = BoundaryCondition(Flux(), nothing)
ImpenetrableBoundaryCondition() = BoundaryCondition(Open(), nothing)
MultiRegionCommunicationBoundaryCondition() = BoundaryCondition(MultiRegionCommunication(), nothing)
DistributedCommunicationBoundaryCondition() = BoundaryCondition(DistributedCommunication(), nothing)
ZipperBoundaryCondition(sign=1) = BoundaryCondition(Zipper(), sign)

FluxBoundaryCondition(val; kwargs...) = BoundaryCondition(Flux(), val; kwargs...)
ValueBoundaryCondition(val; kwargs...) = BoundaryCondition(Value(), val; kwargs...)
GradientBoundaryCondition(val; kwargs...) = BoundaryCondition(Gradient(), val; kwargs...)
OpenBoundaryCondition(val; kwargs...) = BoundaryCondition(Open(nothing), val; kwargs...)
MultiRegionCommunicationBoundaryCondition(val; kwargs...) = BoundaryCondition(MultiRegionCommunication(), val; kwargs...)
DistributedCommunicationBoundaryCondition(val; kwargs...) = BoundaryCondition(DistributedCommunication(), val; kwargs...)
ZipperBoundaryCondition(val; kwargs...) = BoundaryCondition(Zipper(), val; kwargs...)

# Support for various types of boundary conditions.
#
Expand Down
8 changes: 8 additions & 0 deletions src/BoundaryConditions/boundary_condition_classifications.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,11 @@ struct MultiRegionCommunication <: AbstractBoundaryConditionClassification end
A classification specifying a distributed memory communicating boundary condition
"""
struct DistributedCommunication <: AbstractBoundaryConditionClassification end

"""
struct Zipper <: AbstractBoundaryConditionClassification

A classification specifying a Zipper boundary condition where one boundary is folded onto itself.
Used only for a tripolar grid.
"""
struct Zipper <: AbstractBoundaryConditionClassification end
134 changes: 134 additions & 0 deletions src/BoundaryConditions/fill_halo_regions_zipper.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using Oceananigans.Grids: Center, Face
using Oceananigans.Utils: KernelParameters, launch!

"""
ZipperBoundaryCondition(sign = 1)

Create a zipper boundary condition specific to the `TripolarGrid`.
A Zipper boundary condition is similar to a periodic boundary condition, but,
instead of retrieving the value from the opposite boundary, it splits the boundary
in two and retrieves the value from the opposite side of the boundary.
It is possible to think of it as a periodic boundary over a folded domain.

When copying in halos, folded velocities need to switch sign, while tracers or similar fields do not.

Note: the Tripolar boundary condition is particular because the last grid point
at the north edge is repeated for tracers. For this reason we do not start copying the halo
from the last grid point but from the second to last grid point.

Example
=======

Consider the northern edge of a tripolar grid where P indicates the j - location of the poles

```
P P
| | | |
Ny (center) -> u₁ c₁ u₂ c₂ u₃ c₃ u₄ c₄
Ny (face) -> |---- v₁ ----|---- v₂ ----|---- v₃ ----|---- v₄ ----
Nx Nx
(face) (center)
```
The grid ends at `Ny` because it is periodic in nature, but, given the fold,
```
c₁ == c₄
```

and
```
c₂ == c₃
```

This is not the case for the v-velocity (or any field on the j-faces) where the last grid point is not repeated.
"""

#####
##### Outer functions for filling halo regions for Zipper boundary conditions.
#####

@inline function fold_north_face_face!(i, k, grid, sign, c)
Nx, Ny, _ = size(grid)

i′ = Nx - i + 2 # Remember! element Nx + 1 does not exist!
sign = ifelse(i′ > Nx , abs(sign), sign) # for periodic elements we change the sign
i′ = ifelse(i′ > Nx, i′ - Nx, i′) # Periodicity is hardcoded in the x-direction!!
Hy = grid.Hy

for j = 1 : Hy
@inbounds begin
c[i, Ny + j, k] = sign * c[i′, Ny - j + 1, k]
end
end

return nothing
end

@inline function fold_north_face_center!(i, k, grid, sign, c)
Nx, Ny, _ = size(grid)

i′ = Nx - i + 2 # Remember! element Nx + 1 does not exist!
sign = ifelse(i′ > Nx , abs(sign), sign) # for periodic elements we change the sign
i′ = ifelse(i′ > Nx, i′ - Nx, i′) # Periodicity is hardcoded in the x-direction!!
Hy = grid.Hy

for j = 1 : Hy
@inbounds begin
c[i, Ny + j, k] = sign * c[i′, Ny - j, k] # The Ny line is duplicated so we substitute starting Ny-1
end
end

# We substitute the redundant part of the last row to ensure consistency
@inbounds c[i, Ny, k] = ifelse(i > Nx ÷ 2, sign * c[i′, Ny, k], c[i, Ny, k])

return nothing
end

@inline function fold_north_center_face!(i, k, grid, sign, c)
Nx, Ny, _ = size(grid)

i′ = Nx - i + 1
Hy = grid.Hy

for j = 1 : Hy
@inbounds begin
c[i, Ny + j, k] = sign * c[i′, Ny - j + 1, k]
end
end

return nothing
end

@inline function fold_north_center_center!(i, k, grid, sign, c)
Nx, Ny, _ = size(grid)

i′ = Nx - i + 1
Hy = grid.Hy

for j = 1 : Hy
@inbounds begin
c[i, Ny + j, k] = sign * c[i′, Ny - j, k] # The Ny line is duplicated so we substitute starting Ny-1
end
end

# We substitute the redundant part of the last row to ensure consistency
@inbounds c[i, Ny, k] = ifelse(i > Nx ÷ 2, sign * c[i′, Ny, k], c[i, Ny, k])

return nothing
end

const CCLocation = Tuple{<:Center, <:Center, <:Any}
const FCLocation = Tuple{<:Face, <:Center, <:Any}
const CFLocation = Tuple{<:Center, <:Face, <:Any}
const FFLocation = Tuple{<:Face, <:Face, <:Any}

# tracers or similar fields
@inline _fill_north_halo!(i, k, grid, c, bc::ZBC, ::CCLocation, args...) = fold_north_center_center!(i, k, grid, bc.condition, c)

# u-velocity or similar fields
@inline _fill_north_halo!(i, k, grid, u, bc::ZBC, ::FCLocation, args...) = fold_north_face_center!(i, k, grid, bc.condition, u)

# v-velocity or similar fields
@inline _fill_north_halo!(i, k, grid, v, bc::ZBC, ::CFLocation, args...) = fold_north_center_face!(i, k, grid, bc.condition, v)

# vorticity or similar fields
@inline _fill_north_halo!(i, k, grid, ζ, bc::ZBC, ::FFLocation, args...) = fold_north_face_face!(i, k, grid, bc.condition, ζ)
2 changes: 2 additions & 0 deletions src/BoundaryConditions/show_boundary_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bc_str(::IBC) = "Impenetrable"
bc_str(::DFBC) = "Default"
bc_str(::MCBC) = "MultiRegionCommunication"
bc_str(::DCBC) = "DistributedCommunication"
bc_str(::ZBC) = "Zipper"
bc_str(::Nothing) = "Nothing"

#####
Expand All @@ -28,6 +29,7 @@ Base.summary(bc::VBC) = string("ValueBoundaryCondition: ", p
Base.summary(bc::GBC) = string("GradientBoundaryCondition: ", prettysummary(bc.condition))
Base.summary(::PBC) = string("PeriodicBoundaryCondition")
Base.summary(bc::DCBC) = string("DistributedBoundaryCondition: ", prettysummary(bc.condition))
Base.summary(bc::ZBC) = string("ZipperBoundaryCondition: ", prettysummary(bc.condition))

show(io::IO, bc::BoundaryCondition) = print(io, summary(bc))

Expand Down
10 changes: 9 additions & 1 deletion src/Fields/field.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Oceananigans.BoundaryConditions: OBC, MCBC, BoundaryCondition
using Oceananigans.BoundaryConditions: OBC, MCBC, BoundaryCondition, Zipper
using Oceananigans.Grids: parent_index_range, index_range_offset, default_indices, all_indices, validate_indices
using Oceananigans.Grids: index_range_contains

Expand Down Expand Up @@ -80,6 +80,14 @@ function validate_boundary_conditions(loc, grid, bcs)
return nothing
end

# Some special validation for a zipper boundary condition
validate_boundary_condition_location(bc::Zipper, loc::Center, side) =
side == :north ? nothing : throw(ArgumentError("Cannot specify $side boundary condition $bc on a field at $(loc) (north only)!"))

validate_boundary_condition_location(bc::Zipper, loc::Face, side) =
side == :north ? nothing : throw(ArgumentError("Cannot specify $side boundary condition $bc on a field at $(loc) (north only)!"))


#####
##### Some basic constructors
#####
Expand Down
6 changes: 4 additions & 2 deletions src/Oceananigans.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export
# Grids
Center, Face,
Periodic, Bounded, Flat,
RectilinearGrid, LatitudeLongitudeGrid, OrthogonalSphericalShellGrid,
RectilinearGrid, LatitudeLongitudeGrid, OrthogonalSphericalShellGrid, TripolarGrid,
nodes, xnodes, ynodes, rnodes, znodes, λnodes, φnodes,
xspacings, yspacings, rspacings, zspacings, λspacings, φspacings,
minimum_xspacing, minimum_yspacing, minimum_zspacing,
Expand Down Expand Up @@ -208,12 +208,13 @@ include("Operators/Operators.jl")
include("BoundaryConditions/BoundaryConditions.jl")
include("Fields/Fields.jl")
include("AbstractOperations/AbstractOperations.jl")
include("TimeSteppers/TimeSteppers.jl")
include("ImmersedBoundaries/ImmersedBoundaries.jl")
include("TimeSteppers/TimeSteppers.jl")
include("Advection/Advection.jl")
include("Solvers/Solvers.jl")
include("OutputReaders/OutputReaders.jl")
include("DistributedComputations/DistributedComputations.jl")
include("OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl")

# TODO: move here
#include("MultiRegion/MultiRegion.jl")
Expand Down Expand Up @@ -257,6 +258,7 @@ using .OutputReaders
using .Forcings
using .ImmersedBoundaries
using .DistributedComputations
using .OrthogonalSphericalShellGrids
using .Models
using .TimeSteppers
using .Diagnostics
Expand Down
29 changes: 29 additions & 0 deletions src/OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module OrthogonalSphericalShellGrids

# The only thing we need!
export TripolarGrid

using Oceananigans
using Oceananigans.Grids
using Oceananigans.Architectures: device, on_architecture
using Oceananigans.BoundaryConditions
using Oceananigans.Fields: index_binary_search, convert_to_0_360
using Oceananigans.Grids: RightConnected
using Oceananigans.Grids: R_Earth,
halo_size, spherical_area_quadrilateral,
lat_lon_to_cartesian, generate_coordinate, topology

using Oceananigans.Operators
using Oceananigans.Utils: get_cartesian_nodes_and_vertices

using Distances
using Adapt
using KernelAbstractions: @kernel, @index
using KernelAbstractions.Extras.LoopInfo: @unroll
using OffsetArrays

include("generate_tripolar_coordinates.jl")
include("tripolar_grid.jl")
include("tripolar_field_extensions.jl")

end
Loading
Loading