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

Conversation

simone-silvestri
Copy link
Collaborator

@simone-silvestri simone-silvestri commented Nov 11, 2024

Our implementation of the tripolar grid is in https://github.com/CliMA/OrthogonalSphericalShellGrids.jl at the moment.

We have figured out that the implementation of the tripolar grid is very much entangled with Oceananigans because it requires extending a lot of time-stepping specific code.

This leads to delays in development when we have to develop the two packages in tandem.
Therefore, this PR migrates the implementation of the Tripolar grid and its specific methods to Oceananigans.

Edit: This PR implements only the serial version. The distributed TripolarGrid requires a little more work and will come in subsequent PRs

@navidcy navidcy self-requested a review November 11, 2024 10:30
Copy link
Collaborator

@navidcy navidcy left a comment

Choose a reason for hiding this comment

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

nice

we should update

1. [`RectilinearGrid`](@ref Oceananigans.Grids.RectilinearGrid) can be fashioned into lines, rectangles and boxes.
2. [`LatitudeLongitudeGrid`](@ref Oceananigans.Grids.LatitudeLongitudeGrid) represents sectors of thin spherical shells, with cells bounded by lines of constant latitude and longitude.
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)
for recipes that implement some useful `OrthogonalSphericalShellGrid`, including the
["tripolar" grid](https://www.sciencedirect.com/science/article/abs/pii/S0021999196901369).

@navidcy
Copy link
Collaborator

navidcy commented Nov 11, 2024

@simone-silvestri

Which device is meant to be used here?

loop! = _compute_tripolar_coordinates!(device(CPU()), (16, 16), (Nλ, Nφ))

WARNING: both Architectures and CUDA export "device"; uses of it in module Grids must be qualified
Unit tests...: Error During Test at /Users/navid/Research/OC11.jl/test/test_tripolar_grid.jl:31
  Got exception outside of a @test
  UndefVarError: `device` not defined
  Stacktrace:
    [1] (TripolarGrid)(arch::CPU, FT::DataType; size::Tuple{Int64, Int64, Int64}, southernmost_latitude::Int64, halo::Tuple{Int64, Int64, Int64}, radius::Float64, z::Tuple{Int64, Int64}, north_poles_latitude::Int64, first_pole_longitude::Int64)
      @ Oceananigans.Grids ~/Research/OC11.jl/src/Grids/tripolar_grid.jl:108

@glwagner
Copy link
Member

Why draft?

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

Why draft?

I guess because it needs work... Still most test fail. It's not ready for review...

@glwagner
Copy link
Member

Huh true. Just thought it would have been a copy/paste job but maybe there's more to it

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

It shouldn't be hard to fix... I can give it a go later!

@simone-silvestri
Copy link
Collaborator Author

the main problem is that we use Fields and fill_halo_regions! in the construction of the grid. I ll search a way around it

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

This part:

# Boundary conditions to fill halos of the coordinate and metric terms
# We need to define them manually because of the convention in the
# ZipperBoundaryCondition that edge fields need to switch sign (which we definitely do not
# want for coordinates and metrics)
default_boundary_conditions = FieldBoundaryConditions(north = ZipperBoundaryCondition(),
south = nothing, # The south should be `continued`
west = Oceananigans.PeriodicBoundaryCondition(),
east = Oceananigans.PeriodicBoundaryCondition(),
top = nothing,
bottom = nothing)

requires BoundaryConditions before grids?

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

Oh I just saw your comment @simone-silvestri!

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

Damn...

Fields and fill_halo_regions! are also used in the cubed sphere grid also, but that's defined later in the MultiRegion module.

@simone-silvestri
Copy link
Collaborator Author

simone-silvestri commented Nov 12, 2024

We could move the zipper-filling halo kernels in grids and use them just as kernels.
Then later import them in boundary conditions and use them for the ZipperBoundaryCondition.
It is a bit convoluted though.

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

Or we can define the TripolarGrid in a module on its own after Fields/Boundary conditions? It does make sense that it lives in Grids... aaaaargh

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

Btw, here we define a haversine

# Is this the same as in Oceananigans?
# TODO: check it out
function haversine(a, b, radius)
λ₁, φ₁ = a
λ₂, φ₂ = b
x₁, y₁, z₁ = lat_lon_to_cartesian(φ₁, λ₁, radius)
x₂, y₂, z₂ = lat_lon_to_cartesian(φ₂, λ₂, radius)
return radius * acos(max(-1.0, min((x₁ * x₂ + y₁ * y₂ + z₁ * z₂) / radius^2, 1.0)))
end

Elsewhere in Oceananigans we use the Distances.haversine; see https://github.com/JuliaStats/Distances.jl/blob/master/src/haversine.jl

@navidcy
Copy link
Collaborator

navidcy commented Nov 12, 2024

The two are exactly the same; the snippet below demonstrates that:

using Oceananigans.Grids: lat_lon_to_cartesian
using Distances

# Is this the same as in Oceananigans? 
# TODO: check it out
function haversine_simone(a, b, radius)
    λ₁, φ₁ = a
    λ₂, φ₂ = b

    x₁, y₁, z₁ = lat_lon_to_cartesian(φ₁, λ₁, radius)
    x₂, y₂, z₂ = lat_lon_to_cartesian(φ₂, λ₂, radius)

    return radius * acos(max(-1.0, min((x₁ * x₂ + y₁ * y₂ + z₁ * z₂) / radius^2, 1.0)))
end

using Test

for i in 1:100
    (λ1, φ1) = rand()*360, (2rand()-1)*90
    (λ2, φ2) = rand()*360, (2rand()-1)*90

    radius = rand() * 6300e3

    @test haversine_simone((λ1, φ1), (λ2, φ2), radius)  Distances.haversine((λ1, φ1), (λ2, φ2), radius)
end

@simone-silvestri simone-silvestri marked this pull request as ready for review November 15, 2024 08:49
@simone-silvestri
Copy link
Collaborator Author

The tests seem to pass

@simone-silvestri simone-silvestri changed the title Tripolar grid in Oceananigans Tripolar grid in Oceananigans (only serial) Nov 15, 2024
Comment on lines +60 to +61
λ2Ds = (λFF, λFC, λCF, λCC)
φ2Ds = (φFF, φFC, φCF, φCC)
Copy link
Member

Choose a reason for hiding this comment

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

why different notation than usual

using Oceananigans.Utils: KernelParameters, contiguousrange


@kernel function compute_nonorthogonality_angle!(angle, grid, xF, yF, zF)
Copy link
Member

Choose a reason for hiding this comment

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

What's a "nonorthogonality_angle"? Is this the deviation from orthogonality? (So it should be small)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah, it should be small. I am not sure what is acceptable, so I am comparing it here with a cubes sphere

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants