From 2916ad139ff53140d83a2de7db0e0c1512187885 Mon Sep 17 00:00:00 2001 From: "Gregory L. Wagner" Date: Sat, 22 Feb 2025 11:34:44 -0700 Subject: [PATCH] Implement RotatedLatitudeLongitudeGrid (#4108) * Start implementing DisplacedLatitudeLongitudeGrid * Displaced Latlon grid * Change name to rotated lat-lon grid * Update rotation matrices * Add test for RotatedLatLonGrid * Include new time stepping tests * Update validation tests * Reduce range of metric translation * Add extra method for lat-lon-metric --- Project.toml | 1 + src/Grids/Grids.jl | 1 + src/Grids/conformal_cubed_sphere_panel.jl | 678 ++++++ src/Grids/grid_utils.jl | 6 +- src/Grids/new_data.jl | 5 +- src/Grids/orthogonal_spherical_shell_grid.jl | 751 +----- src/Oceananigans.jl | 2 + .../spacings_and_areas_and_volumes.jl | 4 +- .../OrthogonalSphericalShellGrids.jl | 11 + .../rotated_latitude_longitude_grid.jl | 180 ++ test/runtests.jl | 1 + test/test_grids.jl | 14 + ...rthogonal_spherical_shell_time_stepping.jl | 52 + .../Manifest.toml | 2068 +++++++++++++++++ .../Project.toml | 5 + .../polar_turbulence.jl | 108 + .../rotated_lat_lon_splash.jl | 132 ++ 17 files changed, 3343 insertions(+), 676 deletions(-) create mode 100644 src/Grids/conformal_cubed_sphere_panel.jl create mode 100644 src/OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl create mode 100644 src/OrthogonalSphericalShellGrids/rotated_latitude_longitude_grid.jl create mode 100644 test/test_orthogonal_spherical_shell_time_stepping.jl create mode 100644 validation/orthogonal_spherical_shell_grid/Manifest.toml create mode 100644 validation/orthogonal_spherical_shell_grid/Project.toml create mode 100644 validation/orthogonal_spherical_shell_grid/polar_turbulence.jl create mode 100644 validation/orthogonal_spherical_shell_grid/rotated_lat_lon_splash.jl diff --git a/Project.toml b/Project.toml index f609ffecd5..94ca0fc0e5 100644 --- a/Project.toml +++ b/Project.toml @@ -31,6 +31,7 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc" SeawaterPolynomials = "d496a93d-167e-4197-9f49-d3af4ff8fe40" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" TimesDates = "bdfc003b-8df8-5c39-adcd-3a9087f5df4a" diff --git a/src/Grids/Grids.jl b/src/Grids/Grids.jl index 4b331048d3..6b98a1e49f 100644 --- a/src/Grids/Grids.jl +++ b/src/Grids/Grids.jl @@ -131,6 +131,7 @@ include("input_validation.jl") include("grid_generation.jl") include("rectilinear_grid.jl") include("orthogonal_spherical_shell_grid.jl") +include("conformal_cubed_sphere_panel.jl") include("latitude_longitude_grid.jl") end # module diff --git a/src/Grids/conformal_cubed_sphere_panel.jl b/src/Grids/conformal_cubed_sphere_panel.jl new file mode 100644 index 0000000000..dcd698e53a --- /dev/null +++ b/src/Grids/conformal_cubed_sphere_panel.jl @@ -0,0 +1,678 @@ +struct CubedSphereConformalMapping{FT, Rotation} + ξ :: Tuple{FT, FT} + η :: Tuple{FT, FT} + rotation :: Rotation +end + +# TODO: this belongs elsewhere. +const ConformalCubedSpherePanel = OrthogonalSphericalShellGrid{<:Any, FullyConnected, FullyConnected, + <:Any, <:Any, <:Any, + <:CubedSphereConformalMapping} + +const ConformalCubedSpherePanelGrid = OrthogonalSphericalShellGrid{<:Any, + <:Any, + <:Any, + <:Any, + <:Any, + <:Any, + <:CubedSphereConformalMapping} + +# architecture = CPU() default, assuming that a DataType positional arg +# is specifying the floating point type. +conformal_cubed_sphere_panel(FT::DataType; kwargs...) = conformal_cubed_sphere_panel(CPU(), FT; kwargs...) + +function load_and_offset_cubed_sphere_data(file, FT, arch, field_name, loc, topo, N, H) + + data = on_architecture(arch, file[field_name]) + data = convert.(FT, data) + + return offset_data(data, loc[1:2], topo[1:2], N[1:2], H[1:2]) +end + +function conformal_cubed_sphere_panel(filepath::AbstractString, architecture = CPU(), FT = Float64; + panel, Nz, z, + topology = (FullyConnected, FullyConnected, Bounded), + radius = R_Earth, + halo = (4, 4, 4), + rotation = nothing) + + TX, TY, TZ = topology + Hx, Hy, Hz = halo + + ## Read everything from the file except the z-coordinates + + file = jldopen(filepath, "r")["panel$panel"] + + Nξ, Nη = size(file["λᶠᶠᵃ"]) + Hξ, Hη = halo[1], halo[2] + Nξ -= 2Hξ + Nη -= 2Hη + + N = (Nξ, Nη, Nz) + H = halo + + loc_cc = (Center, Center) + loc_fc = (Face, Center) + loc_cf = (Center, Face) + loc_ff = (Face, Face) + + λᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "λᶜᶜᵃ", loc_cc, topology, N, H) + λᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "λᶠᶠᵃ", loc_ff, topology, N, H) + + φᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "φᶜᶜᵃ", loc_cc, topology, N, H) + φᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "φᶠᶠᵃ", loc_ff, topology, N, H) + + Δxᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶜᶜᵃ", loc_cc, topology, N, H) + Δxᶠᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶠᶜᵃ", loc_fc, topology, N, H) + Δxᶜᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶜᶠᵃ", loc_cf, topology, N, H) + Δxᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶠᶠᵃ", loc_ff, topology, N, H) + + Δyᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶜᶜᵃ", loc_cc, topology, N, H) + Δyᶠᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶠᶜᵃ", loc_fc, topology, N, H) + Δyᶜᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶜᶠᵃ", loc_cf, topology, N, H) + Δyᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶠᶠᵃ", loc_ff, topology, N, H) + + Azᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶜᶜᵃ", loc_cc, topology, N, H) + Azᶠᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶠᶜᵃ", loc_fc, topology, N, H) + Azᶜᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶜᶠᵃ", loc_cf, topology, N, H) + Azᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶠᶠᵃ", loc_ff, topology, N, H) + + ## Maybe we won't need these? + Txᶠᶜ = total_length(loc_fc[1](), topology[1](), N[1], H[1]) + Txᶜᶠ = total_length(loc_cf[1](), topology[1](), N[1], H[1]) + Tyᶠᶜ = total_length(loc_fc[2](), topology[2](), N[2], H[2]) + Tyᶜᶠ = total_length(loc_cf[2](), topology[2](), N[2], H[2]) + + λᶠᶜᵃ = offset_data(zeros(architecture, FT, Txᶠᶜ, Tyᶠᶜ), loc_fc, topology[1:2], N[1:2], H[1:2]) + λᶜᶠᵃ = offset_data(zeros(architecture, FT, Txᶜᶠ, Tyᶜᶠ), loc_cf, topology[1:2], N[1:2], H[1:2]) + φᶠᶜᵃ = offset_data(zeros(architecture, FT, Txᶠᶜ, Tyᶠᶜ), loc_fc, topology[1:2], N[1:2], H[1:2]) + φᶜᶠᵃ = offset_data(zeros(architecture, FT, Txᶜᶠ, Tyᶜᶠ), loc_cf, topology[1:2], N[1:2], H[1:2]) + + ## The vertical coordinates can come out of the regular rectilinear grid! + Lz, z = generate_coordinate(FT, topology, (Nξ, Nη, Nz), halo, z, :z, 3, architecture) + + ξ, η = (-1, 1), (-1, 1) + conformal_mapping = CubedSphereConformalMapping(ξ, η, rotation) + + return OrthogonalSphericalShellGrid{TX, TY, TZ}(architecture, Nξ, Nη, Nz, Hx, Hy, Hz, Lz, + λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ, + φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ, + z, + Δxᶜᶜᵃ, Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, + Δyᶜᶜᵃ, Δyᶜᶠᵃ, Δyᶠᶜᵃ, Δyᶠᶠᵃ, + Azᶜᶜᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ, + radius, + conformal_mapping) +end + +function with_halo(new_halo, old_grid::OrthogonalSphericalShellGrid; rotation=nothing) + + size = (old_grid.Nx, old_grid.Ny, old_grid.Nz) + topo = topology(old_grid) + + ξ = old_grid.conformal_mapping.ξ + η = old_grid.conformal_mapping.η + + z = cpu_face_constructor_z(old_grid) + + new_grid = conformal_cubed_sphere_panel(architecture(old_grid), eltype(old_grid); + size, z, ξ, η, + topology = topo, + radius = old_grid.radius, + halo = new_halo, + rotation) + + return new_grid +end + +""" + conformal_cubed_sphere_panel(architecture::AbstractArchitecture = CPU(), + FT::DataType = Float64; + size, + z, + topology = (Bounded, Bounded, Bounded), + ξ = (-1, 1), + η = (-1, 1), + radius = R_Earth, + halo = (1, 1, 1), + rotation = nothing) + +Create a `OrthogonalSphericalShellGrid` that represents a section of a sphere after it has been +conformally mapped from the face of a cube. The cube's coordinates are `ξ` and `η` (which, by default, +both take values in the range ``[-1, 1]``. + +The mapping from the face of the cube to the sphere is done via the [CubedSphere.jl](https://github.com/CliMA/CubedSphere.jl) +package. + +Positional arguments +==================== + +- `architecture`: Specifies whether arrays of coordinates and spacings are stored + on the CPU or GPU. Default: `CPU()`. + +- `FT` : Floating point data type. Default: `Float64`. + +Keyword arguments +================= + +- `size` (required): A 3-tuple prescribing the number of grid points each direction. + +- `z` (required): Either a + 1. 2-tuple that specify the end points of the ``z``-domain, + 2. one-dimensional array specifying the cell interface locations, or + 3. a single-argument function that takes an index and returns cell interface location. + +- `radius`: The radius of the sphere the grid lives on. By default this is equal to the radius of Earth. + +- `halo`: A 3-tuple of integers specifying the size of the halo region of cells surrounding + the physical interior. The default is 1 halo cells in every direction. + +- `rotation :: Rotation`: Rotation of the conformal cubed sphere panel about some axis that passes + through the center of the sphere. If `nothing` is provided (default), then + the panel includes the North Pole of the sphere in its center. For example, + to construct a grid that includes tha South Pole we can pass either + `rotation = RotX(π)` or `rotation = RotY(π)`. + +Examples +======== + +* The default conformal cubed sphere panel grid with `Float64` type: + +```jldoctest +julia> using Oceananigans, Oceananigans.Grids + +julia> grid = conformal_cubed_sphere_panel(size=(36, 34, 25), z=(-1000, 0)) +36×34×25 OrthogonalSphericalShellGrid{Float64, Bounded, Bounded, Bounded} on CPU with 1×1×1 halo and with precomputed metrics +├── centered at: North Pole, (λ, φ) = (0.0, 90.0) +├── longitude: Bounded extent 90.0 degrees variably spaced with min(Δλ)=0.616164, max(Δλ)=2.58892 +├── latitude: Bounded extent 90.0 degrees variably spaced with min(Δφ)=0.664958, max(Δφ)=2.74119 +└── z: Bounded z ∈ [-1000.0, 0.0] regularly spaced with Δz=40.0 +``` + +* The conformal cubed sphere panel that includes the South Pole with `Float32` type: + +```jldoctest +julia> using Oceananigans, Oceananigans.Grids, Rotations + +julia> grid = conformal_cubed_sphere_panel(Float32, size=(36, 34, 25), z=(-1000, 0), rotation=RotY(π)) +36×34×25 OrthogonalSphericalShellGrid{Float32, Bounded, Bounded, Bounded} on CPU with 1×1×1 halo and with precomputed metrics +├── centered at: South Pole, (λ, φ) = (0.0, -90.0) +├── longitude: Bounded extent 90.0 degrees variably spaced with min(Δλ)=0.616167, max(Δλ)=2.58891 +├── latitude: Bounded extent 90.0 degrees variably spaced with min(Δφ)=0.664956, max(Δφ)=2.7412 +└── z: Bounded z ∈ [-1000.0, 0.0] regularly spaced with Δz=40.0 +``` +""" +function conformal_cubed_sphere_panel(architecture::AbstractArchitecture = CPU(), + FT::DataType = Oceananigans.defaults.FloatType; + size, + z, + topology = (Bounded, Bounded, Bounded), + ξ = (-1, 1), + η = (-1, 1), + radius = R_Earth, + halo = (1, 1, 1), + rotation = nothing) + + if architecture == GPU() && !has_cuda() + throw(ArgumentError("Cannot create a GPU grid. No CUDA-enabled GPU was detected!")) + end + + radius = FT(radius) + + TX, TY, TZ = topology + Nξ, Nη, Nz = size + Hx, Hy, Hz = halo + + ## Use a regular rectilinear grid for the face of the cube + + ξη_grid_topology = (Bounded, Bounded, topology[3]) + + # construct the grid on CPU and convert to architecture later... + ξη_grid = RectilinearGrid(CPU(), FT; + size=(Nξ, Nη, Nz), + topology = ξη_grid_topology, + x=ξ, y=η, z, halo) + + ξᶠᵃᵃ = xnodes(ξη_grid, Face()) + ξᶜᵃᵃ = xnodes(ξη_grid, Center()) + ηᵃᶠᵃ = ynodes(ξη_grid, Face()) + ηᵃᶜᵃ = ynodes(ξη_grid, Center()) + + ## The vertical coordinates and metrics can come out of the regular rectilinear grid! + zc = ξη_grid.z + Lz = ξη_grid.Lz + + + ## Compute staggered grid latitude-longitude (φ, λ) coordinates. + + λᶜᶜᵃ = zeros(FT, Nξ , Nη ) + λᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) + λᶜᶠᵃ = zeros(FT, Nξ , Nη+1) + λᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) + + φᶜᶜᵃ = zeros(FT, Nξ , Nη ) + φᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) + φᶜᶠᵃ = zeros(FT, Nξ , Nη+1) + φᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) + + ξS = (ξᶜᵃᵃ, ξᶠᵃᵃ, ξᶜᵃᵃ, ξᶠᵃᵃ) + ηS = (ηᵃᶜᵃ, ηᵃᶜᵃ, ηᵃᶠᵃ, ηᵃᶠᵃ) + λS = (λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ) + φS = (φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ) + + for (ξ, η, λ, φ) in zip(ξS, ηS, λS, φS) + for j in 1:length(η), i in 1:length(ξ) + x, y, z = @inbounds conformal_cubed_sphere_mapping(ξ[i], η[j]) + + if !isnothing(rotation) + x, y, z = rotation * [x, y, z] + end + + @inbounds φ[i, j], λ[i, j] = cartesian_to_lat_lon(x, y, z) + end + end + + any(any.(isnan, λS)) && + @warn "OrthogonalSphericalShellGrid contains a grid point at a pole whose longitude is undefined (NaN)." + + ## Grid metrics + + # Horizontal distances + + #= + Distances Δx and Δy are computed via the haversine formula provided by Distances.jl + package. For example, Δx = Δσ * radius, where Δσ is the central angle that corresponds + to the end points of distance Δx. + + For cells near the boundary of the conformal cubed sphere panel, one of the points + defining, e.g., Δx might lie outside the grid! For example, the central angle + Δxᶠᶜᵃ[1, j] that corresponds to the cell centered at Face 1, Center j is + + Δxᶠᶜᵃ[1, j] = haversine((λᶜᶜᵃ[1, j], φᶜᶜᵃ[1, j]), (λᶜᶜᵃ[0, j], φᶜᶜᵃ[0, j]), radius) + + Notice that, e.g., point (φᶜᶜᵃ[0, j], λᶜᶜᵃ[0, j]) is outside the boundaries of the grid. + In those cases, we employ symmetry arguments and compute, e.g, Δxᶠᶜᵃ[1, j] via + + Δxᶠᶜᵃ[1, j] = 2 * haversine((λᶜᶜᵃ[1, j], φᶜᶜᵃ[1, j]), (λᶠᶜᵃ[1, j], φᶠᶜᵃ[1, j]), radius) + =# + + + Δxᶜᶜᵃ = zeros(FT, Nξ , Nη ) + Δxᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) + Δxᶜᶠᵃ = zeros(FT, Nξ , Nη+1) + Δxᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) + + @inbounds begin + #Δxᶜᶜᵃ + + for i in 1:Nξ, j in 1:Nη + Δxᶜᶜᵃ[i, j] = haversine((λᶠᶜᵃ[i+1, j], φᶠᶜᵃ[i+1, j]), (λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), radius) + end + + + # Δxᶠᶜᵃ + + for j in 1:Nη, i in 2:Nξ + Δxᶠᶜᵃ[i, j] = haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶜᶜᵃ[i-1, j], φᶜᶜᵃ[i-1, j]), radius) + end + + for j in 1:Nη + i = 1 + Δxᶠᶜᵃ[i, j] = 2haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶠᶜᵃ[ i , j], φᶠᶜᵃ[ i , j]), radius) + end + + for j in 1:Nη + i = Nξ+1 + Δxᶠᶜᵃ[i, j] = 2haversine((λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), (λᶜᶜᵃ[i-1, j], φᶜᶜᵃ[i-1, j]), radius) + end + + + # Δxᶜᶠᵃ + + for j in 1:Nη+1, i in 1:Nξ + Δxᶜᶠᵃ[i, j] = haversine((λᶠᶠᵃ[i+1, j], φᶠᶠᵃ[i+1, j]), (λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), radius) + end + + + # Δxᶠᶠᵃ + + for j in 1:Nη+1, i in 2:Nξ + Δxᶠᶠᵃ[i, j] = haversine((λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), (λᶜᶠᵃ[i-1, j], φᶜᶠᵃ[i-1, j]), radius) + end + + for j in 1:Nη+1 + i = 1 + Δxᶠᶠᵃ[i, j] = 2haversine((λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), (λᶠᶠᵃ[ i , j], φᶠᶠᵃ[ i , j]), radius) + end + + for j in 1:Nη+1 + i = Nξ+1 + Δxᶠᶠᵃ[i, j] = 2haversine((λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), (λᶜᶠᵃ[i-1, j], φᶜᶠᵃ[i-1, j]), radius) + end + end + + Δyᶜᶜᵃ = zeros(FT, Nξ , Nη ) + Δyᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) + Δyᶜᶠᵃ = zeros(FT, Nξ , Nη+1) + Δyᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) + + @inbounds begin + # Δyᶜᶜᵃ + + for j in 1:Nη, i in 1:Nξ + Δyᶜᶜᵃ[i, j] = haversine((λᶜᶠᵃ[i, j+1], φᶜᶠᵃ[i, j+1]), (λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), radius) + end + + + # Δyᶜᶠᵃ + + for j in 2:Nη, i in 1:Nξ + Δyᶜᶠᵃ[i, j] = haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶜᶜᵃ[i, j-1], φᶜᶜᵃ[i, j-1]), radius) + end + + for i in 1:Nξ + j = 1 + Δyᶜᶠᵃ[i, j] = 2haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶜᶠᵃ[i, j ], φᶜᶠᵃ[i, j ]), radius) + end + + for i in 1:Nξ + j = Nη+1 + Δyᶜᶠᵃ[i, j] = 2haversine((λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), (λᶜᶜᵃ[i, j-1], φᶜᶜᵃ[i, j-1]), radius) + end + + + # Δyᶠᶜᵃ + + for j in 1:Nη, i in 1:Nξ+1 + Δyᶠᶜᵃ[i, j] = haversine((λᶠᶠᵃ[i, j+1], φᶠᶠᵃ[i, j+1]), (λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), radius) + end + + + # Δyᶠᶠᵃ + + for j in 2:Nη, i in 1:Nξ+1 + Δyᶠᶠᵃ[i, j] = haversine((λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), (λᶠᶜᵃ[i, j-1], φᶠᶜᵃ[i, j-1]), radius) + end + + for i in 1:Nξ+1 + j = 1 + Δyᶠᶠᵃ[i, j] = 2haversine((λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), (λᶠᶠᵃ[i, j ], φᶠᶠᵃ[i, j ]), radius) + end + + for i in 1:Nξ+1 + j = Nη+1 + Δyᶠᶠᵃ[i, j] = 2haversine((λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), (λᶠᶜᵃ[i, j-1], φᶠᶜᵃ[i, j-1]), radius) + end + end + + # Area metrics + + #= + The areas Az correspond to spherical quadrilaterals. To compute Az first we + find the vertices a, b, c, d of the corresponding quadrilateral and then use + + Az = spherical_area_quadrilateral(a, b, c, d) * radius^2 + + For quadrilaterals near the boundary of the conformal cubed sphere panel, some of the + vertices lie outside the grid! For example, the area Azᶠᶜᵃ[1, j] corresponds to a + quadrilateral with vertices: + + a = (φᶜᶠᵃ[0, j ], λᶜᶠᵃ[0, j ]) + b = (φᶜᶠᵃ[1, j ], λᶜᶠᵃ[1, j ]) + c = (φᶜᶠᵃ[1, j+1], λᶜᶠᵃ[1, j+1]) + d = (φᶜᶠᵃ[0, j+1], λᶜᶠᵃ[0, j+1]) + + Notice that vertices a and d are outside the boundaries of the grid. In those cases, we + employ symmetry arguments and, e.g., compute Azᶠᶜᵃ[1, j] as + + 2 * spherical_area_quadrilateral(ã, b, c, d̃) * radius^2 + + where, ã = (φᶠᶠᵃ[1, j], λᶠᶠᵃ[1, j]) and d̃ = (φᶠᶠᵃ[1, j+1], λᶠᶠᵃ[1, j+1]) + =# + + Azᶜᶜᵃ = zeros(FT, Nξ , Nη ) + Azᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) + Azᶜᶠᵃ = zeros(FT, Nξ , Nη+1) + Azᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) + + @inbounds begin + # Azᶜᶜᵃ + + for j in 1:Nη, i in 1:Nξ + a = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + b = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j ], λᶠᶠᵃ[i+1, j ], 1) + c = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j+1], λᶠᶠᵃ[i+1, j+1], 1) + d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j+1], λᶠᶠᵃ[ i , j+1], 1) + + Azᶜᶜᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + + # Azᶠᶜᵃ + + for j in 1:Nη, i in 2:Nξ + a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) + b = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) + c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j+1], λᶜᶠᵃ[ i , j+1], 1) + d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j+1], λᶜᶠᵃ[i-1, j+1], 1) + + Azᶠᶜᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for j in 1:Nη + i = 1 + a = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + b = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) + c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j+1], λᶜᶠᵃ[ i , j+1], 1) + d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j+1], λᶠᶠᵃ[ i , j+1], 1) + + Azᶠᶜᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for j in 1:Nη + i = Nξ+1 + a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) + b = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + c = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j+1], λᶠᶠᵃ[ i , j+1], 1) + d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j+1], λᶜᶠᵃ[i-1, j+1], 1) + + Azᶠᶜᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + + # Azᶜᶠᵃ + + for j in 2:Nη, i in 1:Nξ + a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) + b = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j-1], λᶠᶜᵃ[i+1, j-1], 1) + c = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j ], λᶠᶜᵃ[i+1, j ], 1) + d = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) + + Azᶜᶠᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for i in 1:Nξ + j = 1 + a = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + b = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j ], λᶠᶠᵃ[i+1, j ], 1) + c = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j ], λᶠᶜᵃ[i+1, j ], 1) + d = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) + + Azᶜᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for i in 1:Nξ + j = Nη+1 + a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) + b = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j-1], λᶠᶜᵃ[i+1, j-1], 1) + c = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j ], λᶠᶠᵃ[i+1, j ], 1) + d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + + Azᶜᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + + # Azᶠᶠᵃ + + for j in 2:Nη, i in 2:Nξ + a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) + b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) + c = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j ], λᶜᶜᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) + + Azᶠᶠᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for i in 2:Nξ + j = 1 + a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) + b = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) + c = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j ], λᶜᶜᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) + + Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for i in 2:Nξ + j = Nη+1 + a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) + b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) + c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) + + Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for j in 2:Nη + i = 1 + a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) + b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) + c = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j ], λᶜᶜᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) + + Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + for j in 2:Nη + i = Nξ+1 + a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) + b = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) + c = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) + + Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + i = 1 + j = 1 + a = lat_lon_to_cartesian(φᶠᶠᵃ[i, j], λᶠᶠᵃ[i, j], 1) + b = lat_lon_to_cartesian(φᶜᶠᵃ[i, j], λᶜᶠᵃ[i, j], 1) + c = lat_lon_to_cartesian(φᶜᶜᵃ[i, j], λᶜᶜᵃ[i, j], 1) + d = lat_lon_to_cartesian(φᶠᶜᵃ[i, j], λᶠᶜᵃ[i, j], 1) + + Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + + i = Nξ+1 + j = Nη+1 + a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) + b = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) + c = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) + + Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + + i = Nξ+1 + j = 1 + a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j], 1) + b = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j], 1) + c = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) + + Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + + i = 1 + j = Nη+1 + a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) + b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) + c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) + d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) + + Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 + end + + # In all computations above we used (Bounded, Bounded, topology[3]) for ξ-η grid. + # This was done to ensure that we had information for the faces at the boundary of + # the grid. + # + # Now we take care the coordinate and metric arrays given the `topology` prescribed. + + warnings = false + + args = topology, (Nξ, Nη, Nz), (Hx, Hy, Hz) + + λᶜᶜᵃ = add_halos(λᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) + λᶠᶜᵃ = add_halos(λᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) + λᶜᶠᵃ = add_halos(λᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) + λᶠᶠᵃ = add_halos(λᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) + + φᶜᶜᵃ = add_halos(φᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) + φᶠᶜᵃ = add_halos(φᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) + φᶜᶠᵃ = add_halos(φᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) + φᶠᶠᵃ = add_halos(φᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) + + Δxᶜᶜᵃ = add_halos(Δxᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) + Δxᶠᶜᵃ = add_halos(Δxᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) + Δxᶜᶠᵃ = add_halos(Δxᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) + Δxᶠᶠᵃ = add_halos(Δxᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) + + Δyᶜᶜᵃ = add_halos(Δyᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) + Δyᶠᶜᵃ = add_halos(Δyᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) + Δyᶜᶠᵃ = add_halos(Δyᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) + Δyᶠᶠᵃ = add_halos(Δyᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) + + Azᶜᶜᵃ = add_halos(Azᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) + Azᶠᶜᵃ = add_halos(Azᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) + Azᶜᶠᵃ = add_halos(Azᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) + Azᶠᶠᵃ = add_halos(Azᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) + + coordinate_arrays = (λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ, + φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ, + zc) + + metric_arrays = (Δxᶜᶜᵃ, Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, + Δyᶜᶜᵃ, Δyᶜᶠᵃ, Δyᶠᶜᵃ, Δyᶠᶠᵃ, + Azᶜᶜᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ) + + conformal_mapping = CubedSphereConformalMapping(ξ, η, rotation) + + grid = OrthogonalSphericalShellGrid{TX, TY, TZ}(CPU(), Nξ, Nη, Nz, Hx, Hy, Hz, Lz, + coordinate_arrays..., + metric_arrays..., + radius, + conformal_mapping) + + fill_metric_halo_regions!(grid) + + # now convert to proper architecture + + coordinate_arrays = (grid.λᶜᶜᵃ, grid.λᶠᶜᵃ, grid.λᶜᶠᵃ, grid.λᶠᶠᵃ, + grid.φᶜᶜᵃ, grid.φᶠᶜᵃ, grid.φᶜᶠᵃ, grid.φᶠᶠᵃ, + grid.z) + + metric_arrays = (grid.Δxᶜᶜᵃ, grid.Δxᶠᶜᵃ, grid.Δxᶜᶠᵃ, grid.Δxᶠᶠᵃ, + grid.Δyᶜᶜᵃ, grid.Δyᶜᶠᵃ, grid.Δyᶠᶜᵃ, grid.Δyᶠᶠᵃ, + grid.Azᶜᶜᵃ, grid.Azᶠᶜᵃ, grid.Azᶜᶠᵃ, grid.Azᶠᶠᵃ) + + coordinate_arrays = map(a -> on_architecture(architecture, a), coordinate_arrays) + + metric_arrays = map(a -> on_architecture(architecture, a), metric_arrays) + + grid = OrthogonalSphericalShellGrid{TX, TY, TZ}(architecture, Nξ, Nη, Nz, Hx, Hy, Hz, Lz, + coordinate_arrays..., + metric_arrays..., + radius, + conformal_mapping) + return grid +end + + diff --git a/src/Grids/grid_utils.jl b/src/Grids/grid_utils.jl index 7bf74fbdeb..afd8d7c9f2 100644 --- a/src/Grids/grid_utils.jl +++ b/src/Grids/grid_utils.jl @@ -471,13 +471,9 @@ julia> add_halos(data, loc, topo, (Nx, Ny, Nz), (1, 2, 0)) ``` """ function add_halos(data, loc, topo, sz, halo_sz; warnings=true) - Nx, Ny, Nz = size(data) - arch = architecture(data) - - # bring to CPU - map(a -> on_architecture(CPU(), a), data) + map(a -> on_architecture(CPU(), a), data) # bring to CPU nx, ny, nz = total_length(loc[1](), topo[1](), sz[1], 0), total_length(loc[2](), topo[2](), sz[2], 0), diff --git a/src/Grids/new_data.jl b/src/Grids/new_data.jl index 30072d73f0..621655f8b3 100644 --- a/src/Grids/new_data.jl +++ b/src/Grids/new_data.jl @@ -63,8 +63,8 @@ Return an `OffsetArray` of zeros of float type `FT` on `arch`itecture, with indices corresponding to a field on a `grid` of `size(grid)` and located at `loc`. """ function new_data(FT::DataType, arch, loc, topo, sz, halo_sz, indices=default_indices(length(loc))) - Tx, Ty, Tz = total_size(loc, topo, sz, halo_sz, indices) - underlying_data = zeros(arch, FT, Tx, Ty, Tz) + Tsz = total_size(loc, topo, sz, halo_sz, indices) + underlying_data = zeros(arch, FT, Tsz...) indices = validate_indices(indices, loc, topo, sz, halo_sz) return offset_data(underlying_data, loc, topo, sz, halo_sz, indices) end @@ -73,3 +73,4 @@ new_data(FT::DataType, grid::AbstractGrid, loc, indices=default_indices(length(l new_data(FT, architecture(grid), loc, topology(grid), size(grid), halo_size(grid), indices) new_data(grid::AbstractGrid, loc, indices=default_indices) = new_data(eltype(grid), grid, loc, indices) + diff --git a/src/Grids/orthogonal_spherical_shell_grid.jl b/src/Grids/orthogonal_spherical_shell_grid.jl index 4b81f4e4c7..fe772d17ad 100644 --- a/src/Grids/orthogonal_spherical_shell_grid.jl +++ b/src/Grids/orthogonal_spherical_shell_grid.jl @@ -9,12 +9,6 @@ using Adapt: adapt_structure using Oceananigans using Oceananigans.Grids: prettysummary, coordinate_summary, BoundedTopology, length -struct CubedSphereConformalMapping{FT, Rotation} - ξ :: Tuple{FT, FT} - η :: Tuple{FT, FT} - rotation :: Rotation -end - struct OrthogonalSphericalShellGrid{FT, TX, TY, TZ, CZ, A, C, Arch} <: AbstractHorizontallyCurvilinearGrid{FT, TX, TY, TZ, CZ, Arch} architecture :: Arch Nx :: Int @@ -51,7 +45,7 @@ struct OrthogonalSphericalShellGrid{FT, TX, TY, TZ, CZ, A, C, Arch} <: AbstractH OrthogonalSphericalShellGrid{TX, TY, TZ}(architecture::Arch, Nx, Ny, Nz, Hx, Hy, Hz, - Lz :: FT, + Lz :: FT, λᶜᶜᵃ :: A, λᶠᶜᵃ :: A, λᶜᶠᵃ :: A, λᶠᶠᵃ :: A, φᶜᶜᵃ :: A, φᶠᶜᵃ :: A, φᶜᶠᵃ :: A, φᶠᶠᵃ :: A, z :: CZ, Δxᶜᶜᵃ :: A, Δxᶠᶜᵃ :: A, Δxᶜᶠᵃ :: A, Δxᶠᶠᵃ :: A, @@ -73,7 +67,6 @@ end const OSSG = OrthogonalSphericalShellGrid const ZRegOSSG = OrthogonalSphericalShellGrid{<:Any, <:Any, <:Any, <:Any, <:RegularVerticalCoordinate} const ZRegOrthogonalSphericalShellGrid = ZRegOSSG -const ConformalCubedSpherePanel = OrthogonalSphericalShellGrid{<:Any, FullyConnected, FullyConnected, <:Any, <:Any, <:Any, <:CubedSphereConformalMapping} # convenience constructor for OSSG without any conformal_mapping properties OrthogonalSphericalShellGrid(architecture, Nx, Ny, Nz, Hx, Hy, Hz, Lz, @@ -85,556 +78,6 @@ OrthogonalSphericalShellGrid(architecture, Nx, Ny, Nz, Hx, Hy, Hz, Lz, Δxᶜᶜᵃ, Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, Δyᶜᶜᵃ, Δyᶜᶠᵃ, Δyᶠᶜᵃ, Δyᶠᶠᵃ, Azᶜᶜᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ, radius, nothing) -""" - conformal_cubed_sphere_panel(architecture::AbstractArchitecture = CPU(), - FT::DataType = Float64; - size, - z, - topology = (Bounded, Bounded, Bounded), - ξ = (-1, 1), - η = (-1, 1), - radius = R_Earth, - halo = (1, 1, 1), - rotation = nothing) - -Create a `OrthogonalSphericalShellGrid` that represents a section of a sphere after it has been -conformally mapped from the face of a cube. The cube's coordinates are `ξ` and `η` (which, by default, -both take values in the range ``[-1, 1]``. - -The mapping from the face of the cube to the sphere is done via the [CubedSphere.jl](https://github.com/CliMA/CubedSphere.jl) -package. - -Positional arguments -==================== - -- `architecture`: Specifies whether arrays of coordinates and spacings are stored - on the CPU or GPU. Default: `CPU()`. - -- `FT` : Floating point data type. Default: `Float64`. - -Keyword arguments -================= - -- `size` (required): A 3-tuple prescribing the number of grid points each direction. - -- `z` (required): Either a - 1. 2-tuple that specify the end points of the ``z``-domain, - 2. one-dimensional array specifying the cell interface locations, or - 3. a single-argument function that takes an index and returns cell interface location. - -- `radius`: The radius of the sphere the grid lives on. By default this is equal to the radius of Earth. - -- `halo`: A 3-tuple of integers specifying the size of the halo region of cells surrounding - the physical interior. The default is 1 halo cells in every direction. - -- `rotation :: Rotation`: Rotation of the conformal cubed sphere panel about some axis that passes - through the center of the sphere. If `nothing` is provided (default), then - the panel includes the North Pole of the sphere in its center. For example, - to construct a grid that includes tha South Pole we can pass either - `rotation = RotX(π)` or `rotation = RotY(π)`. - -Examples -======== - -* The default conformal cubed sphere panel grid with `Float64` type: - -```jldoctest -julia> using Oceananigans, Oceananigans.Grids - -julia> grid = conformal_cubed_sphere_panel(size=(36, 34, 25), z=(-1000, 0)) -36×34×25 OrthogonalSphericalShellGrid{Float64, Bounded, Bounded, Bounded} on CPU with 1×1×1 halo and with precomputed metrics -├── centered at: North Pole, (λ, φ) = (0.0, 90.0) -├── longitude: Bounded extent 90.0 degrees variably spaced with min(Δλ)=0.616164, max(Δλ)=2.58892 -├── latitude: Bounded extent 90.0 degrees variably spaced with min(Δφ)=0.664958, max(Δφ)=2.74119 -└── z: Bounded z ∈ [-1000.0, 0.0] regularly spaced with Δz=40.0 -``` - -* The conformal cubed sphere panel that includes the South Pole with `Float32` type: - -```jldoctest -julia> using Oceananigans, Oceananigans.Grids, Rotations - -julia> grid = conformal_cubed_sphere_panel(Float32, size=(36, 34, 25), z=(-1000, 0), rotation=RotY(π)) -36×34×25 OrthogonalSphericalShellGrid{Float32, Bounded, Bounded, Bounded} on CPU with 1×1×1 halo and with precomputed metrics -├── centered at: South Pole, (λ, φ) = (0.0, -90.0) -├── longitude: Bounded extent 90.0 degrees variably spaced with min(Δλ)=0.616167, max(Δλ)=2.58891 -├── latitude: Bounded extent 90.0 degrees variably spaced with min(Δφ)=0.664956, max(Δφ)=2.7412 -└── z: Bounded z ∈ [-1000.0, 0.0] regularly spaced with Δz=40.0 -``` -""" -function conformal_cubed_sphere_panel(architecture::AbstractArchitecture = CPU(), - FT::DataType = Oceananigans.defaults.FloatType; - size, - z, - topology = (Bounded, Bounded, Bounded), - ξ = (-1, 1), - η = (-1, 1), - radius = R_Earth, - halo = (1, 1, 1), - rotation = nothing) - - if architecture == GPU() && !has_cuda() - throw(ArgumentError("Cannot create a GPU grid. No CUDA-enabled GPU was detected!")) - end - - radius = FT(radius) - - TX, TY, TZ = topology - Nξ, Nη, Nz = size - Hx, Hy, Hz = halo - - ## Use a regular rectilinear grid for the face of the cube - - ξη_grid_topology = (Bounded, Bounded, topology[3]) - - # construct the grid on CPU and convert to architecture later... - ξη_grid = RectilinearGrid(CPU(), FT; - size=(Nξ, Nη, Nz), - topology = ξη_grid_topology, - x=ξ, y=η, z, halo) - - ξᶠᵃᵃ = xnodes(ξη_grid, Face()) - ξᶜᵃᵃ = xnodes(ξη_grid, Center()) - ηᵃᶠᵃ = ynodes(ξη_grid, Face()) - ηᵃᶜᵃ = ynodes(ξη_grid, Center()) - - ## The vertical coordinates and metrics can come out of the regular rectilinear grid! - zc = ξη_grid.z - Lz = ξη_grid.Lz - - - ## Compute staggered grid latitude-longitude (φ, λ) coordinates. - - λᶜᶜᵃ = zeros(FT, Nξ , Nη ) - λᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) - λᶜᶠᵃ = zeros(FT, Nξ , Nη+1) - λᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) - - φᶜᶜᵃ = zeros(FT, Nξ , Nη ) - φᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) - φᶜᶠᵃ = zeros(FT, Nξ , Nη+1) - φᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) - - ξS = (ξᶜᵃᵃ, ξᶠᵃᵃ, ξᶜᵃᵃ, ξᶠᵃᵃ) - ηS = (ηᵃᶜᵃ, ηᵃᶜᵃ, ηᵃᶠᵃ, ηᵃᶠᵃ) - λS = (λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ) - φS = (φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ) - - for (ξ, η, λ, φ) in zip(ξS, ηS, λS, φS) - for j in 1:length(η), i in 1:length(ξ) - x, y, z = @inbounds conformal_cubed_sphere_mapping(ξ[i], η[j]) - - if !isnothing(rotation) - x, y, z = rotation * [x, y, z] - end - - @inbounds φ[i, j], λ[i, j] = cartesian_to_lat_lon(x, y, z) - end - end - - any(any.(isnan, λS)) && - @warn "OrthogonalSphericalShellGrid contains a grid point at a pole whose longitude is undefined (NaN)." - - ## Grid metrics - - # Horizontal distances - - #= - Distances Δx and Δy are computed via the haversine formula provided by Distances.jl - package. For example, Δx = Δσ * radius, where Δσ is the central angle that corresponds - to the end points of distance Δx. - - For cells near the boundary of the conformal cubed sphere panel, one of the points - defining, e.g., Δx might lie outside the grid! For example, the central angle - Δxᶠᶜᵃ[1, j] that corresponds to the cell centered at Face 1, Center j is - - Δxᶠᶜᵃ[1, j] = haversine((λᶜᶜᵃ[1, j], φᶜᶜᵃ[1, j]), (λᶜᶜᵃ[0, j], φᶜᶜᵃ[0, j]), radius) - - Notice that, e.g., point (φᶜᶜᵃ[0, j], λᶜᶜᵃ[0, j]) is outside the boundaries of the grid. - In those cases, we employ symmetry arguments and compute, e.g, Δxᶠᶜᵃ[1, j] via - - Δxᶠᶜᵃ[1, j] = 2 * haversine((λᶜᶜᵃ[1, j], φᶜᶜᵃ[1, j]), (λᶠᶜᵃ[1, j], φᶠᶜᵃ[1, j]), radius) - =# - - - Δxᶜᶜᵃ = zeros(FT, Nξ , Nη ) - Δxᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) - Δxᶜᶠᵃ = zeros(FT, Nξ , Nη+1) - Δxᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) - - @inbounds begin - #Δxᶜᶜᵃ - - for i in 1:Nξ, j in 1:Nη - Δxᶜᶜᵃ[i, j] = haversine((λᶠᶜᵃ[i+1, j], φᶠᶜᵃ[i+1, j]), (λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), radius) - end - - - # Δxᶠᶜᵃ - - for j in 1:Nη, i in 2:Nξ - Δxᶠᶜᵃ[i, j] = haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶜᶜᵃ[i-1, j], φᶜᶜᵃ[i-1, j]), radius) - end - - for j in 1:Nη - i = 1 - Δxᶠᶜᵃ[i, j] = 2haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶠᶜᵃ[ i , j], φᶠᶜᵃ[ i , j]), radius) - end - - for j in 1:Nη - i = Nξ+1 - Δxᶠᶜᵃ[i, j] = 2haversine((λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), (λᶜᶜᵃ[i-1, j], φᶜᶜᵃ[i-1, j]), radius) - end - - - # Δxᶜᶠᵃ - - for j in 1:Nη+1, i in 1:Nξ - Δxᶜᶠᵃ[i, j] = haversine((λᶠᶠᵃ[i+1, j], φᶠᶠᵃ[i+1, j]), (λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), radius) - end - - - # Δxᶠᶠᵃ - - for j in 1:Nη+1, i in 2:Nξ - Δxᶠᶠᵃ[i, j] = haversine((λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), (λᶜᶠᵃ[i-1, j], φᶜᶠᵃ[i-1, j]), radius) - end - - for j in 1:Nη+1 - i = 1 - Δxᶠᶠᵃ[i, j] = 2haversine((λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), (λᶠᶠᵃ[ i , j], φᶠᶠᵃ[ i , j]), radius) - end - - for j in 1:Nη+1 - i = Nξ+1 - Δxᶠᶠᵃ[i, j] = 2haversine((λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), (λᶜᶠᵃ[i-1, j], φᶜᶠᵃ[i-1, j]), radius) - end - end - - Δyᶜᶜᵃ = zeros(FT, Nξ , Nη ) - Δyᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) - Δyᶜᶠᵃ = zeros(FT, Nξ , Nη+1) - Δyᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) - - @inbounds begin - # Δyᶜᶜᵃ - - for j in 1:Nη, i in 1:Nξ - Δyᶜᶜᵃ[i, j] = haversine((λᶜᶠᵃ[i, j+1], φᶜᶠᵃ[i, j+1]), (λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), radius) - end - - - # Δyᶜᶠᵃ - - for j in 2:Nη, i in 1:Nξ - Δyᶜᶠᵃ[i, j] = haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶜᶜᵃ[i, j-1], φᶜᶜᵃ[i, j-1]), radius) - end - - for i in 1:Nξ - j = 1 - Δyᶜᶠᵃ[i, j] = 2haversine((λᶜᶜᵃ[i, j], φᶜᶜᵃ[i, j]), (λᶜᶠᵃ[i, j ], φᶜᶠᵃ[i, j ]), radius) - end - - for i in 1:Nξ - j = Nη+1 - Δyᶜᶠᵃ[i, j] = 2haversine((λᶜᶠᵃ[i, j], φᶜᶠᵃ[i, j]), (λᶜᶜᵃ[i, j-1], φᶜᶜᵃ[i, j-1]), radius) - end - - - # Δyᶠᶜᵃ - - for j in 1:Nη, i in 1:Nξ+1 - Δyᶠᶜᵃ[i, j] = haversine((λᶠᶠᵃ[i, j+1], φᶠᶠᵃ[i, j+1]), (λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), radius) - end - - - # Δyᶠᶠᵃ - - for j in 2:Nη, i in 1:Nξ+1 - Δyᶠᶠᵃ[i, j] = haversine((λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), (λᶠᶜᵃ[i, j-1], φᶠᶜᵃ[i, j-1]), radius) - end - - for i in 1:Nξ+1 - j = 1 - Δyᶠᶠᵃ[i, j] = 2haversine((λᶠᶜᵃ[i, j], φᶠᶜᵃ[i, j]), (λᶠᶠᵃ[i, j ], φᶠᶠᵃ[i, j ]), radius) - end - - for i in 1:Nξ+1 - j = Nη+1 - Δyᶠᶠᵃ[i, j] = 2haversine((λᶠᶠᵃ[i, j], φᶠᶠᵃ[i, j]), (λᶠᶜᵃ[i, j-1], φᶠᶜᵃ[i, j-1]), radius) - end - end - - # Area metrics - - #= - The areas Az correspond to spherical quadrilaterals. To compute Az first we - find the vertices a, b, c, d of the corresponding quadrilateral and then use - - Az = spherical_area_quadrilateral(a, b, c, d) * radius^2 - - For quadrilaterals near the boundary of the conformal cubed sphere panel, some of the - vertices lie outside the grid! For example, the area Azᶠᶜᵃ[1, j] corresponds to a - quadrilateral with vertices: - - a = (φᶜᶠᵃ[0, j ], λᶜᶠᵃ[0, j ]) - b = (φᶜᶠᵃ[1, j ], λᶜᶠᵃ[1, j ]) - c = (φᶜᶠᵃ[1, j+1], λᶜᶠᵃ[1, j+1]) - d = (φᶜᶠᵃ[0, j+1], λᶜᶠᵃ[0, j+1]) - - Notice that vertices a and d are outside the boundaries of the grid. In those cases, we - employ symmetry arguments and, e.g., compute Azᶠᶜᵃ[1, j] as - - 2 * spherical_area_quadrilateral(ã, b, c, d̃) * radius^2 - - where, ã = (φᶠᶠᵃ[1, j], λᶠᶠᵃ[1, j]) and d̃ = (φᶠᶠᵃ[1, j+1], λᶠᶠᵃ[1, j+1]) - =# - - Azᶜᶜᵃ = zeros(FT, Nξ , Nη ) - Azᶠᶜᵃ = zeros(FT, Nξ+1, Nη ) - Azᶜᶠᵃ = zeros(FT, Nξ , Nη+1) - Azᶠᶠᵃ = zeros(FT, Nξ+1, Nη+1) - - @inbounds begin - # Azᶜᶜᵃ - - for j in 1:Nη, i in 1:Nξ - a = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - b = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j ], λᶠᶠᵃ[i+1, j ], 1) - c = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j+1], λᶠᶠᵃ[i+1, j+1], 1) - d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j+1], λᶠᶠᵃ[ i , j+1], 1) - - Azᶜᶜᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - - # Azᶠᶜᵃ - - for j in 1:Nη, i in 2:Nξ - a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) - b = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) - c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j+1], λᶜᶠᵃ[ i , j+1], 1) - d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j+1], λᶜᶠᵃ[i-1, j+1], 1) - - Azᶠᶜᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for j in 1:Nη - i = 1 - a = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - b = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) - c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j+1], λᶜᶠᵃ[ i , j+1], 1) - d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j+1], λᶠᶠᵃ[ i , j+1], 1) - - Azᶠᶜᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for j in 1:Nη - i = Nξ+1 - a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) - b = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - c = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j+1], λᶠᶠᵃ[ i , j+1], 1) - d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j+1], λᶜᶠᵃ[i-1, j+1], 1) - - Azᶠᶜᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - - # Azᶜᶠᵃ - - for j in 2:Nη, i in 1:Nξ - a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) - b = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j-1], λᶠᶜᵃ[i+1, j-1], 1) - c = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j ], λᶠᶜᵃ[i+1, j ], 1) - d = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) - - Azᶜᶠᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for i in 1:Nξ - j = 1 - a = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - b = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j ], λᶠᶠᵃ[i+1, j ], 1) - c = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j ], λᶠᶜᵃ[i+1, j ], 1) - d = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) - - Azᶜᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for i in 1:Nξ - j = Nη+1 - a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) - b = lat_lon_to_cartesian(φᶠᶜᵃ[i+1, j-1], λᶠᶜᵃ[i+1, j-1], 1) - c = lat_lon_to_cartesian(φᶠᶠᵃ[i+1, j ], λᶠᶠᵃ[i+1, j ], 1) - d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - - Azᶜᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - - # Azᶠᶠᵃ - - for j in 2:Nη, i in 2:Nξ - a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) - b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) - c = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j ], λᶜᶜᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) - - Azᶠᶠᵃ[i, j] = spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for i in 2:Nξ - j = 1 - a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) - b = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) - c = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j ], λᶜᶜᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) - - Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for i in 2:Nξ - j = Nη+1 - a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) - b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) - c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) - - Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for j in 2:Nη - i = 1 - a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) - b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) - c = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j ], λᶜᶜᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) - - Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - for j in 2:Nη - i = Nξ+1 - a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) - b = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) - c = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) - - Azᶠᶠᵃ[i, j] = 2 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - i = 1 - j = 1 - a = lat_lon_to_cartesian(φᶠᶠᵃ[i, j], λᶠᶠᵃ[i, j], 1) - b = lat_lon_to_cartesian(φᶜᶠᵃ[i, j], λᶜᶠᵃ[i, j], 1) - c = lat_lon_to_cartesian(φᶜᶜᵃ[i, j], λᶜᶜᵃ[i, j], 1) - d = lat_lon_to_cartesian(φᶠᶜᵃ[i, j], λᶠᶜᵃ[i, j], 1) - - Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - - i = Nξ+1 - j = Nη+1 - a = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j-1], λᶜᶜᵃ[i-1, j-1], 1) - b = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) - c = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j ], 1) - - Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - - i = Nξ+1 - j = 1 - a = lat_lon_to_cartesian(φᶜᶠᵃ[i-1, j ], λᶜᶠᵃ[i-1, j], 1) - b = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j], 1) - c = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j ], λᶠᶜᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶜᶜᵃ[i-1, j ], λᶜᶜᵃ[i-1, j ], 1) - - Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - - i = 1 - j = Nη+1 - a = lat_lon_to_cartesian(φᶠᶜᵃ[ i , j-1], λᶠᶜᵃ[ i , j-1], 1) - b = lat_lon_to_cartesian(φᶜᶜᵃ[ i , j-1], λᶜᶜᵃ[ i , j-1], 1) - c = lat_lon_to_cartesian(φᶜᶠᵃ[ i , j ], λᶜᶠᵃ[ i , j ], 1) - d = lat_lon_to_cartesian(φᶠᶠᵃ[ i , j ], λᶠᶠᵃ[ i , j ], 1) - - Azᶠᶠᵃ[i, j] = 4 * spherical_area_quadrilateral(a, b, c, d) * radius^2 - end - - # In all computations above we used (Bounded, Bounded, topology[3]) for ξ-η grid. - # This was done to ensure that we had information for the faces at the boundary of - # the grid. - # - # Now we take care the coordinate and metric arrays given the `topology` prescribed. - - warnings = false - - args = topology, (Nξ, Nη, Nz), (Hx, Hy, Hz) - - λᶜᶜᵃ = add_halos(λᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) - λᶠᶜᵃ = add_halos(λᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) - λᶜᶠᵃ = add_halos(λᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) - λᶠᶠᵃ = add_halos(λᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) - - φᶜᶜᵃ = add_halos(φᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) - φᶠᶜᵃ = add_halos(φᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) - φᶜᶠᵃ = add_halos(φᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) - φᶠᶠᵃ = add_halos(φᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) - - Δxᶜᶜᵃ = add_halos(Δxᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) - Δxᶠᶜᵃ = add_halos(Δxᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) - Δxᶜᶠᵃ = add_halos(Δxᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) - Δxᶠᶠᵃ = add_halos(Δxᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) - - Δyᶜᶜᵃ = add_halos(Δyᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) - Δyᶠᶜᵃ = add_halos(Δyᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) - Δyᶜᶠᵃ = add_halos(Δyᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) - Δyᶠᶠᵃ = add_halos(Δyᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) - - Azᶜᶜᵃ = add_halos(Azᶜᶜᵃ, (Center, Center, Nothing), args...; warnings) - Azᶠᶜᵃ = add_halos(Azᶠᶜᵃ, (Face, Center, Nothing), args...; warnings) - Azᶜᶠᵃ = add_halos(Azᶜᶠᵃ, (Center, Face, Nothing), args...; warnings) - Azᶠᶠᵃ = add_halos(Azᶠᶠᵃ, (Face, Face, Nothing), args...; warnings) - - coordinate_arrays = (λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ, - φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ, - zc) - - metric_arrays = (Δxᶜᶜᵃ, Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, - Δyᶜᶜᵃ, Δyᶜᶠᵃ, Δyᶠᶜᵃ, Δyᶠᶠᵃ, - Azᶜᶜᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ) - - conformal_mapping = CubedSphereConformalMapping(ξ, η, rotation) - - grid = OrthogonalSphericalShellGrid{TX, TY, TZ}(CPU(), Nξ, Nη, Nz, Hx, Hy, Hz, Lz, - coordinate_arrays..., - metric_arrays..., - radius, - conformal_mapping) - - fill_metric_halo_regions!(grid) - - # now convert to proper architecture - - coordinate_arrays = (grid.λᶜᶜᵃ, grid.λᶠᶜᵃ, grid.λᶜᶠᵃ, grid.λᶠᶠᵃ, - grid.φᶜᶜᵃ, grid.φᶠᶜᵃ, grid.φᶜᶠᵃ, grid.φᶠᶠᵃ, - grid.z) - - metric_arrays = (grid.Δxᶜᶜᵃ, grid.Δxᶠᶜᵃ, grid.Δxᶜᶠᵃ, grid.Δxᶠᶠᵃ, - grid.Δyᶜᶜᵃ, grid.Δyᶜᶠᵃ, grid.Δyᶠᶜᵃ, grid.Δyᶠᶠᵃ, - grid.Azᶜᶜᵃ, grid.Azᶠᶜᵃ, grid.Azᶜᶠᵃ, grid.Azᶠᶠᵃ) - - coordinate_arrays = map(a -> on_architecture(architecture, a), coordinate_arrays) - - metric_arrays = map(a -> on_architecture(architecture, a), metric_arrays) - - grid = OrthogonalSphericalShellGrid{TX, TY, TZ}(architecture, Nξ, Nη, Nz, Hx, Hy, Hz, Lz, - coordinate_arrays..., - metric_arrays..., - radius, - conformal_mapping) - return grid -end - """ fill_metric_halo_regions_x!(metric, ℓx, ℓy, tx, ty, Nx, Ny, Hx, Hy) @@ -652,6 +95,7 @@ function fill_metric_halo_regions_x!(metric, ℓx, ℓy, tx::BoundedTopology, ty for i in 0:-1:-Hx+1 metric[i, j] = metric[i+1, j] end + # fill east halos for i in Nx⁺+1:Nx⁺+Hx metric[i, j] = metric[i-1, j] @@ -786,7 +230,6 @@ end function lat_lon_to_cartesian(lat, lon, radius) abs(lat) > 90 && error("lat must be within -90 ≤ lat ≤ 90") - return [lat_lon_to_x(lat, lon, radius), lat_lon_to_y(lat, lon, radius), lat_lon_to_z(lat, lon, radius)] end @@ -794,94 +237,6 @@ lat_lon_to_x(lat, lon, radius) = radius * cosd(lon) * cosd(lat) lat_lon_to_y(lat, lon, radius) = radius * sind(lon) * cosd(lat) lat_lon_to_z(lat, lon, radius) = radius * sind(lat) -# architecture = CPU() default, assuming that a DataType positional arg -# is specifying the floating point type. -conformal_cubed_sphere_panel(FT::DataType; kwargs...) = conformal_cubed_sphere_panel(CPU(), FT; kwargs...) - -function load_and_offset_cubed_sphere_data(file, FT, arch, field_name, loc, topo, N, H) - - data = on_architecture(arch, file[field_name]) - data = convert.(FT, data) - - return offset_data(data, loc[1:2], topo[1:2], N[1:2], H[1:2]) -end - -function conformal_cubed_sphere_panel(filepath::AbstractString, architecture = CPU(), FT = Float64; - panel, Nz, z, - topology = (FullyConnected, FullyConnected, Bounded), - radius = R_Earth, - halo = (4, 4, 4), - rotation = nothing) - - TX, TY, TZ = topology - Hx, Hy, Hz = halo - - ## Read everything from the file except the z-coordinates - - file = jldopen(filepath, "r")["panel$panel"] - - Nξ, Nη = size(file["λᶠᶠᵃ"]) - Hξ, Hη = halo[1], halo[2] - Nξ -= 2Hξ - Nη -= 2Hη - - N = (Nξ, Nη, Nz) - H = halo - - loc_cc = (Center, Center) - loc_fc = (Face, Center) - loc_cf = (Center, Face) - loc_ff = (Face, Face) - - λᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "λᶜᶜᵃ", loc_cc, topology, N, H) - λᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "λᶠᶠᵃ", loc_ff, topology, N, H) - - φᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "φᶜᶜᵃ", loc_cc, topology, N, H) - φᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "φᶠᶠᵃ", loc_ff, topology, N, H) - - Δxᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶜᶜᵃ", loc_cc, topology, N, H) - Δxᶠᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶠᶜᵃ", loc_fc, topology, N, H) - Δxᶜᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶜᶠᵃ", loc_cf, topology, N, H) - Δxᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δxᶠᶠᵃ", loc_ff, topology, N, H) - - Δyᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶜᶜᵃ", loc_cc, topology, N, H) - Δyᶠᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶠᶜᵃ", loc_fc, topology, N, H) - Δyᶜᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶜᶠᵃ", loc_cf, topology, N, H) - Δyᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Δyᶠᶠᵃ", loc_ff, topology, N, H) - - Azᶜᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶜᶜᵃ", loc_cc, topology, N, H) - Azᶠᶜᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶠᶜᵃ", loc_fc, topology, N, H) - Azᶜᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶜᶠᵃ", loc_cf, topology, N, H) - Azᶠᶠᵃ = load_and_offset_cubed_sphere_data(file, FT, architecture, "Azᶠᶠᵃ", loc_ff, topology, N, H) - - ## Maybe we won't need these? - Txᶠᶜ = total_length(loc_fc[1](), topology[1](), N[1], H[1]) - Txᶜᶠ = total_length(loc_cf[1](), topology[1](), N[1], H[1]) - Tyᶠᶜ = total_length(loc_fc[2](), topology[2](), N[2], H[2]) - Tyᶜᶠ = total_length(loc_cf[2](), topology[2](), N[2], H[2]) - - λᶠᶜᵃ = offset_data(zeros(architecture, FT, Txᶠᶜ, Tyᶠᶜ), loc_fc, topology[1:2], N[1:2], H[1:2]) - λᶜᶠᵃ = offset_data(zeros(architecture, FT, Txᶜᶠ, Tyᶜᶠ), loc_cf, topology[1:2], N[1:2], H[1:2]) - φᶠᶜᵃ = offset_data(zeros(architecture, FT, Txᶠᶜ, Tyᶠᶜ), loc_fc, topology[1:2], N[1:2], H[1:2]) - φᶜᶠᵃ = offset_data(zeros(architecture, FT, Txᶜᶠ, Tyᶜᶠ), loc_cf, topology[1:2], N[1:2], H[1:2]) - - ## The vertical coordinates can come out of the regular rectilinear grid! - Lz, z = generate_coordinate(FT, topology, (Nξ, Nη, Nz), halo, z, :z, 3, architecture) - - ξ, η = (-1, 1), (-1, 1) - conformal_mapping = CubedSphereConformalMapping(ξ, η, rotation) - - return OrthogonalSphericalShellGrid{TX, TY, TZ}(architecture, Nξ, Nη, Nz, Hx, Hy, Hz, Lz, - λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ, - φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ, - z, - Δxᶜᶜᵃ, Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, - Δyᶜᶜᵃ, Δyᶜᶠᵃ, Δyᶠᶜᵃ, Δyᶠᶠᵃ, - Azᶜᶜᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ, - radius, - conformal_mapping) -end - function on_architecture(arch::AbstractSerialArchitecture, grid::OrthogonalSphericalShellGrid) coordinates = (:λᶜᶜᵃ, @@ -970,6 +325,88 @@ function Base.summary(grid::OrthogonalSphericalShellGrid) " and ", metric_computation) end +function new_metric(FT, arch, (LX, LY), topo, (Nx, Ny), (Hx, Hy)) + # boost horizontal metrics by 2? + Nx′ = Nx + 2 + Ny′ = Ny + 2 + Hx′ = Hx + 2 + Hy′ = Hy + 2 + #metric_3d = new_data(FT, arch, (LX, LY, Nothing), topo, (Nx′, Ny′, 1), halo) + #metric = dropdims(metric_3d, dims=3) + metric = new_data(FT, arch, (LX, LY), topo, (Nx′, Ny′), (Hx′, Hy′)) + return metric +end + +""" + OrthogonalSphericalShellGrid(arch=CPU(), FT=Float64; size, z, + radius = R_Earth, + conformal_mapping = nothing, + halo = (3, 3, 3), + topology = (Bounded, Bounded, Bounded)) + +Create an OrthogonalSphericalShellGrid with empty horizontal metrics. +""" +function OrthogonalSphericalShellGrid(arch::AbstractArchitecture = CPU(), + FT::DataType = Oceananigans.defaults.FloatType; + size, + z, + radius = R_Earth, + conformal_mapping = nothing, + halo = (3, 3, 3), # TODO: support Flat directions + topology = (Bounded, Bounded, Bounded)) + + h_size = size[1:2] + h_topo = topology[1:2] + h_halo = halo[1:2] + + λᶜᶜᵃ = new_metric(FT, arch, (Center, Center), h_topo, h_size, h_halo) + λᶠᶜᵃ = new_metric(FT, arch, (Face, Center), h_topo, h_size, h_halo) + λᶜᶠᵃ = new_metric(FT, arch, (Center, Face), h_topo, h_size, h_halo) + λᶠᶠᵃ = new_metric(FT, arch, (Face, Face), h_topo, h_size, h_halo) + + φᶜᶜᵃ = new_metric(FT, arch, (Center, Center), h_topo, h_size, h_halo) + φᶠᶜᵃ = new_metric(FT, arch, (Face, Center), h_topo, h_size, h_halo) + φᶜᶠᵃ = new_metric(FT, arch, (Center, Face), h_topo, h_size, h_halo) + φᶠᶠᵃ = new_metric(FT, arch, (Face, Face), h_topo, h_size, h_halo) + + Δxᶜᶜᵃ = new_metric(FT, arch, (Center, Center), h_topo, h_size, h_halo) + Δxᶠᶜᵃ = new_metric(FT, arch, (Face, Center), h_topo, h_size, h_halo) + Δxᶜᶠᵃ = new_metric(FT, arch, (Center, Face), h_topo, h_size, h_halo) + Δxᶠᶠᵃ = new_metric(FT, arch, (Face, Face), h_topo, h_size, h_halo) + + Δyᶜᶜᵃ = new_metric(FT, arch, (Center, Center), h_topo, h_size, h_halo) + Δyᶠᶜᵃ = new_metric(FT, arch, (Face, Center), h_topo, h_size, h_halo) + Δyᶜᶠᵃ = new_metric(FT, arch, (Center, Face), h_topo, h_size, h_halo) + Δyᶠᶠᵃ = new_metric(FT, arch, (Face, Face), h_topo, h_size, h_halo) + + Azᶜᶜᵃ = new_metric(FT, arch, (Center, Center), h_topo, h_size, h_halo) + Azᶠᶜᵃ = new_metric(FT, arch, (Face, Center), h_topo, h_size, h_halo) + Azᶜᶠᵃ = new_metric(FT, arch, (Center, Face), h_topo, h_size, h_halo) + Azᶠᶠᵃ = new_metric(FT, arch, (Face, Face), h_topo, h_size, h_halo) + + Lz, z = generate_coordinate(FT, topology, size, halo, z, :z, 3, arch) + + coordinate_arrays = (λᶜᶜᵃ, λᶠᶜᵃ, λᶜᶠᵃ, λᶠᶠᵃ, + φᶜᶜᵃ, φᶠᶜᵃ, φᶜᶠᵃ, φᶠᶠᵃ, + z) + + metric_arrays = (Δxᶜᶜᵃ, Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, + Δyᶜᶜᵃ, Δyᶜᶠᵃ, Δyᶠᶜᵃ, Δyᶠᶠᵃ, + Azᶜᶜᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ) + + Nx, Ny, Nz = size + Hx, Hy, Hz = halo + TX, TY, TZ = topology + + grid = OrthogonalSphericalShellGrid{TX, TY, TZ}(arch, Nx, Ny, Nz, Hx, Hy, Hz, Lz, + coordinate_arrays..., + metric_arrays..., + radius, + conformal_mapping) + + return grid +end + """ get_center_and_extents_of_shell(grid::OSSG) @@ -1071,26 +508,6 @@ function Base.show(io::IO, grid::OrthogonalSphericalShellGrid, withsummary=true) "└── ", z_summary) end -function with_halo(new_halo, old_grid::OrthogonalSphericalShellGrid; rotation=nothing) - - size = (old_grid.Nx, old_grid.Ny, old_grid.Nz) - topo = topology(old_grid) - - ξ = old_grid.conformal_mapping.ξ - η = old_grid.conformal_mapping.η - - z = cpu_face_constructor_z(old_grid) - - new_grid = conformal_cubed_sphere_panel(architecture(old_grid), eltype(old_grid); - size, z, ξ, η, - topology = topo, - radius = old_grid.radius, - halo = new_halo, - rotation) - - return new_grid -end - function nodes(grid::OSSG, ℓx, ℓy, ℓz; reshape=false, with_halos=false) λ = λnodes(grid, ℓx, ℓy, ℓz; with_halos) φ = φnodes(grid, ℓx, ℓy, ℓz; with_halos) diff --git a/src/Oceananigans.jl b/src/Oceananigans.jl index e70c9c095a..2fb3247fbc 100644 --- a/src/Oceananigans.jl +++ b/src/Oceananigans.jl @@ -213,6 +213,7 @@ include("Grids/Grids.jl") include("Utils/Utils.jl") include("Logger.jl") include("Operators/Operators.jl") +include("OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl") include("BoundaryConditions/BoundaryConditions.jl") include("Fields/Fields.jl") include("AbstractOperations/AbstractOperations.jl") @@ -254,6 +255,7 @@ using .Architectures using .Utils using .Advection using .Grids +using .OrthogonalSphericalShellGrids using .BoundaryConditions using .Fields using .Coriolis diff --git a/src/Operators/spacings_and_areas_and_volumes.jl b/src/Operators/spacings_and_areas_and_volumes.jl index 9f8f866a3e..ab065cf628 100644 --- a/src/Operators/spacings_and_areas_and_volumes.jl +++ b/src/Operators/spacings_and_areas_and_volumes.jl @@ -173,7 +173,7 @@ end ##### ##### -##### Two - Dimensional Horizontal Spacings +##### Two-dimensional horizontal spacings ##### ##### @@ -265,7 +265,7 @@ for L1 in (:ᶜ, :ᶠ), L2 in (:ᶜ, :ᶠ) @inline $Azˡˡᵃ(i, j, k, grid) = $Δxˡˡᵃ(i, j, k, grid) * $Δyˡˡᵃ(i, j, k, grid) end - for L3 in (:ᶜ, :ᶠ) + for L3 in (:ᶜ, :ᶠ) # 3D spacings Δxˡˡˡ = Symbol(:Δx, L1, L2, L3) Δyˡˡˡ = Symbol(:Δy, L1, L2, L3) diff --git a/src/OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl b/src/OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl new file mode 100644 index 0000000000..6efedb0cda --- /dev/null +++ b/src/OrthogonalSphericalShellGrids/OrthogonalSphericalShellGrids.jl @@ -0,0 +1,11 @@ +module OrthogonalSphericalShellGrids + +import Oceananigans +using Oceananigans.Architectures: AbstractArchitecture, CPU, architecture +using Oceananigans.Grids: OrthogonalSphericalShellGrid, R_Earth, halo_size +using Oceananigans.Utils: launch! +using KernelAbstractions: @kernel, @index + +include("rotated_latitude_longitude_grid.jl") + +end # module diff --git a/src/OrthogonalSphericalShellGrids/rotated_latitude_longitude_grid.jl b/src/OrthogonalSphericalShellGrids/rotated_latitude_longitude_grid.jl new file mode 100644 index 0000000000..c088caca80 --- /dev/null +++ b/src/OrthogonalSphericalShellGrids/rotated_latitude_longitude_grid.jl @@ -0,0 +1,180 @@ +using Oceananigans.Grids: LatitudeLongitudeGrid +using Oceananigans.Utils: KernelParameters +using StaticArrays +using LinearAlgebra + +struct LatitudeLongitudeRotation{FT} + north_pole :: FT +end + +const RotatedLatitudeLongitudeGrid = OrthogonalSphericalShellGrid{<:Any, + <:Any, + <:Any, + <:Any, + <:Any, + <:Any, + <:LatitudeLongitudeRotation} + +# Helper function (TODO: define Operators before grids...) +@inline lat_lon_metric(m, i, j) = @inbounds m[i, j] +@inline lat_lon_metric(m::AbstractVector, i, j) = @inbounds m[j] +@inline lat_lon_metric(m::Number, j) = m +@inline lat_lon_metric(m::Number, i, j) = m + +function latitude_longitude_shift((λ₀, φ₀)) + Δλ = - λ₀ + Δφ = - φ₀ + return Δλ, Δφ +end + +function RotatedLatitudeLongitudeGrid(arch::AbstractArchitecture = CPU(), + FT::DataType = Oceananigans.defaults.FloatType; + size, + north_pole, + longitude, + latitude, + z, + halo = (3, 3, 3), + radius = R_Earth, + topology = (Bounded, Bounded, Bounded)) + + Δλ, Δφ = latitude_longitude_shift(north_pole) + shifted_longitude = longitude # .+ Δλ + shifted_latitude = latitude #.+ Δφ + shifted_halo = halo .+ 1 + source_grid = LatitudeLongitudeGrid(arch, FT; size, z, topology, radius, + halo = shifted_halo, + latitude = shifted_latitude, + longitude = shifted_longitude) + Nx, Ny, Nz = size + Hx, Hy, Hz = halo_size(source_grid) + Lz = source_grid.Lz + + conformal_mapping = LatitudeLongitudeRotation(north_pole) + grid = OrthogonalSphericalShellGrid(arch, FT; size, z, radius, halo, topology, conformal_mapping) + rotate_metrics!(grid, source_grid) + + return grid +end + +function rotate_metrics!(grid, shifted_lat_lon_grid) + arch = architecture(grid) + Nx, Ny, _ = size(grid) + Hx, Hy, _ = halo_size(grid) + parameters = KernelParameters(-Hx:Nx+Hx+1, -Hy:Ny+Hy+1) + launch!(arch, grid, parameters, _rotate_metrics!, grid, shifted_lat_lon_grid) + return nothing +end + +# Convert from Spherical to Cartesian +function spherical_to_cartesian(λ, φ, r=1) + x = r * cos(φ) * cos(λ) + y = r * cos(φ) * sin(λ) + z = r * sin(φ) + return SVector(x, y, z) +end + +# Convert from Cartesian to Spherical +function cartesian_to_spherical(X) + x, y, z = X + r = norm(X) + φ = asin(z / r) + λ = atan(y, x) + return λ, φ +end + +# Rotation about x-axis by dλ (Change in Longitude) +x_rotation(dλ) = @SMatrix [1 0 0 + 0 cos(dλ) -sin(dλ) + 0 sin(dλ) cos(dλ)] + +# Rotation about y-axis by dφ (Change in Latitude) +y_rotation(dφ) = @SMatrix [ cos(dφ) 0 sin(dφ) + 0 1 0 + -sin(dφ) 0 cos(dφ)] + +# Rotation about z-axis by dλ (Change in Longitude) +z_rotation(dλ) = @SMatrix [cos(dλ) -sin(dλ) 0 + sin(dλ) cos(dλ) 0 + 0 0 1] + +# Perform the rotation +function rotate_coordinates(λ′, φ′, λ₀, φ₀) + λ′ *= π/180 + φ′ *= π/180 + λ₀ *= π/180 + φ₀ *= π/180 + + dλ = - λ₀ + dφ = π/2 - φ₀ + + # Convert to Cartesian + X′ = spherical_to_cartesian(λ′, φ′) + + # Rotate Cartesian coordinates + Rx = x_rotation(dλ) + Ry = y_rotation(dφ) + Rz = z_rotation(dλ) + #X = Rz * Ry * X′ + X = Rx * Ry * X′ + + # Convert back to Spherical + λ, φ = cartesian_to_spherical(X) + + λ *= 180/π + φ *= 180/π + + return λ, φ +end + +@kernel function _rotate_metrics!(grid, source_grid) + i, j = @index(Global, NTuple) + + λ₀, φ₀ = grid.conformal_mapping.north_pole + + @inbounds begin + # Shifted metrics + λ′ = source_grid.λᶜᵃᵃ[i] + φ′ = lat_lon_metric(source_grid.φᵃᶜᵃ, i, j) + λ, φ = rotate_coordinates(λ′, φ′, λ₀, φ₀) + grid.λᶜᶜᵃ[i, j] = λ + grid.φᶜᶜᵃ[i, j] = φ + + λ′ = source_grid.λᶠᵃᵃ[i] + φ′ = lat_lon_metric(source_grid.φᵃᶜᵃ, i, j) + λ, φ = rotate_coordinates(λ′, φ′, λ₀, φ₀) + grid.λᶠᶜᵃ[i, j] = λ + grid.φᶠᶜᵃ[i, j] = φ + + λ′ = source_grid.λᶜᵃᵃ[i] + φ′ = lat_lon_metric(source_grid.φᵃᶠᵃ, i, j) + λ, φ = rotate_coordinates(λ′, φ′, λ₀, φ₀) + grid.λᶜᶠᵃ[i, j] = λ + grid.φᶜᶠᵃ[i, j] = φ + + λ′ = source_grid.λᶠᵃᵃ[i] + φ′ = lat_lon_metric(source_grid.φᵃᶠᵃ, i, j) + λ, φ = rotate_coordinates(λ′, φ′, λ₀, φ₀) + grid.λᶠᶠᵃ[i, j] = λ + grid.φᶠᶠᵃ[i, j] = φ + + # Directly copiable metrics: + grid.Δxᶜᶜᵃ[i, j] = lat_lon_metric(source_grid.Δxᶜᶜᵃ, i, j) + grid.Δxᶠᶜᵃ[i, j] = lat_lon_metric(source_grid.Δxᶠᶜᵃ, i, j) + grid.Δxᶜᶠᵃ[i, j] = lat_lon_metric(source_grid.Δxᶜᶠᵃ, i, j) + grid.Δxᶠᶠᵃ[i, j] = lat_lon_metric(source_grid.Δxᶠᶠᵃ, i, j) + + grid.Azᶜᶜᵃ[i, j] = lat_lon_metric(source_grid.Azᶜᶜᵃ, i, j) + grid.Azᶠᶜᵃ[i, j] = lat_lon_metric(source_grid.Azᶠᶜᵃ, i, j) + grid.Azᶜᶠᵃ[i, j] = lat_lon_metric(source_grid.Azᶜᶠᵃ, i, j) + grid.Azᶠᶠᵃ[i, j] = lat_lon_metric(source_grid.Azᶠᶠᵃ, i, j) + + grid.Δyᶜᶠᵃ[i, j] = lat_lon_metric(source_grid.Δyᶜᶠᵃ, i, j) + grid.Δyᶠᶜᵃ[i, j] = lat_lon_metric(source_grid.Δyᶠᶜᵃ, i, j) + + # Note transposition of location + grid.Δyᶜᶜᵃ[i, j] = lat_lon_metric(source_grid.Δyᶠᶜᵃ, i, j) + grid.Δyᶠᶠᵃ[i, j] = lat_lon_metric(source_grid.Δyᶜᶠᵃ, i, j) + end +end + diff --git a/test/runtests.jl b/test/runtests.jl index 3a4458e1c4..77cc128e01 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -137,6 +137,7 @@ CUDA.allowscalar() do include("test_dynamics.jl") include("test_biogeochemistry.jl") include("test_seawater_density.jl") + include("test_orthogonal_spherical_shell_time_stepping.jl") end end diff --git a/test/test_grids.jl b/test/test_grids.jl index ba687172cc..125a4d1dda 100644 --- a/test/test_grids.jl +++ b/test/test_grids.jl @@ -5,6 +5,8 @@ using Oceananigans.Grids: total_extent, ColumnEnsembleSize, xspacings, yspacings, zspacings, xnode, ynode, znode, λnode, φnode, λspacings, φspacings + +using Oceananigans.OrthogonalSphericalShellGrids: RotatedLatitudeLongitudeGrid using Oceananigans.Operators: Δx, Δy, Δz, Δλ, Δφ, Ax, Ay, Az, volume using Oceananigans.Operators: Δxᶠᶜᵃ, Δxᶜᶠᵃ, Δxᶠᶠᵃ, Δxᶜᶜᵃ, Δyᶠᶜᵃ, Δyᶜᶠᵃ, Azᶠᶜᵃ, Azᶜᶠᵃ, Azᶠᶠᵃ, Azᶜᶜᵃ @@ -1053,6 +1055,18 @@ end @test grid isa OrthogonalSphericalShellGrid + grid = RotatedLatitudeLongitudeGrid(size = (10, 10, 1), + latitude = (-60, 60), + longitude = (-60, 60), + z = (-1000, 0), + north_pole = (0, 0), + topology = (Bounded, Bounded, Bounded)) + + @test grid isa OrthogonalSphericalShellGrid + @test grid isa RotatedLatitudeLongitudeGrid + @test grid.Lz == 1000 + @test size(grid) == (10, 10, 1) + for arch in archs for FT in float_types z = (0, 1) diff --git a/test/test_orthogonal_spherical_shell_time_stepping.jl b/test/test_orthogonal_spherical_shell_time_stepping.jl new file mode 100644 index 0000000000..e9388e2add --- /dev/null +++ b/test/test_orthogonal_spherical_shell_time_stepping.jl @@ -0,0 +1,52 @@ +include("dependencies_for_runtests.jl") + +using Random +using Oceananigans.OrthogonalSphericalShellGrids: RotatedLatitudeLongitudeGrid + +@testset "OrthogonalSphericalShellGrid time stepping" begin + @info "Testing OrthogonalSphericalShellGrid time stepping..." + + size = (64, 64, 2) + latitude = (-60, 60) + longitude = (-60, 60) + z = (-1000, 0) + topology = (Bounded, Bounded, Bounded) + + η₀ = 1 + Δ = 10 + ηᵢ(λ, φ, z) = η₀ * exp(-(λ^2 + φ^2) / 2Δ^2) + + g1 = LatitudeLongitudeGrid(; size, latitude, longitude, z, topology) + g2 = RotatedLatitudeLongitudeGrid(; size, latitude, longitude, z, topology, north_pole=(0, 0)) + + @test g1 isa LatitudeLongitudeGrid + @test !(g2 isa LatitudeLongitudeGrid) + @test g2 isa OrthogonalSphericalShellGrid + + momentum_advection = VectorInvariant() + closure = ScalarDiffusivity(ν=2e-4, κ=2e-4) + m1 = HydrostaticFreeSurfaceModel(grid=g1; closure, momentum_advection) + m2 = HydrostaticFreeSurfaceModel(grid=g2; closure, momentum_advection) + + Random.seed!(123) + ϵᵢ(λ, φ, z) = 1e-6 * randn() + set!(m1, η=ηᵢ, u=ϵᵢ, v=ϵᵢ) + + set!(m2, η = interior(m1.free_surface.η), + u = interior(m1.velocities.u), + v = interior(m1.velocities.v)) + + @test interior(m1.free_surface.η) == interior(m2.free_surface.η) + @test interior(m1.velocities.u) == interior(m2.velocities.u) + @test interior(m1.velocities.v) == interior(m2.velocities.v) + + for model in (m1, m2) + simulation = Simulation(model, Δt=3minutes, stop_iteration=100) + run!(simulation) + end + + @test interior(m1.free_surface.η) == interior(m2.free_surface.η) + @test interior(m1.velocities.u) == interior(m2.velocities.u) + @test interior(m1.velocities.v) == interior(m2.velocities.v) +end + diff --git a/validation/orthogonal_spherical_shell_grid/Manifest.toml b/validation/orthogonal_spherical_shell_grid/Manifest.toml new file mode 100644 index 0000000000..ceb5f685fc --- /dev/null +++ b/validation/orthogonal_spherical_shell_grid/Manifest.toml @@ -0,0 +1,2068 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.8" +manifest_format = "2.0" +project_hash = "76c3fbea14501ed0ca742639f453959f157733d4" + +[[deps.AbstractFFTs]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.5.0" +weakdeps = ["ChainRulesCore", "Test"] + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" + +[[deps.AbstractTrees]] +git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177" +uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" +version = "0.4.5" + +[[deps.Adapt]] +deps = ["LinearAlgebra", "Requires"] +git-tree-sha1 = "cd8b948862abee8f3d3e9b73a102a9ca924debb0" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "4.2.0" +weakdeps = ["SparseArrays", "StaticArrays"] + + [deps.Adapt.extensions] + AdaptSparseArraysExt = "SparseArrays" + AdaptStaticArraysExt = "StaticArrays" + +[[deps.AdaptivePredicates]] +git-tree-sha1 = "7e651ea8d262d2d74ce75fdf47c4d63c07dba7a6" +uuid = "35492f91-a3bd-45ad-95db-fcad7dcfedb7" +version = "1.2.0" + +[[deps.AliasTables]] +deps = ["PtrArrays", "Random"] +git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff" +uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8" +version = "1.1.3" + +[[deps.Animations]] +deps = ["Colors"] +git-tree-sha1 = "e092fa223bf66a3c41f9c022bd074d916dc303e7" +uuid = "27a7e980-b3e6-11e9-2bcd-0b925532e340" +version = "0.4.2" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.1" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[deps.Atomix]] +deps = ["UnsafeAtomics"] +git-tree-sha1 = "93da6c8228993b0052e358ad592ee7c1eccaa639" +uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458" +version = "1.1.0" + + [deps.Atomix.extensions] + AtomixCUDAExt = "CUDA" + AtomixMetalExt = "Metal" + AtomixOpenCLExt = "OpenCL" + AtomixoneAPIExt = "oneAPI" + + [deps.Atomix.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" + OpenCL = "08131aa3-fb12-5dee-8b74-c09406e224a2" + oneAPI = "8f75cd03-7ff8-4ecb-9b8f-daf728133b1b" + +[[deps.Automa]] +deps = ["PrecompileTools", "SIMD", "TranscodingStreams"] +git-tree-sha1 = "a8f503e8e1a5f583fbef15a8440c8c7e32185df2" +uuid = "67c07d97-cdcb-5c2c-af73-a7f9c32a568b" +version = "1.1.0" + +[[deps.AxisAlgorithms]] +deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"] +git-tree-sha1 = "01b8ccb13d68535d73d2b0c23e39bd23155fb712" +uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950" +version = "1.1.0" + +[[deps.AxisArrays]] +deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"] +git-tree-sha1 = "16351be62963a67ac4083f748fdb3cca58bfd52f" +uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9" +version = "0.4.7" + +[[deps.BFloat16s]] +deps = ["LinearAlgebra", "Printf", "Random", "Test"] +git-tree-sha1 = "2c7cc21e8678eff479978a0a2ef5ce2f51b63dff" +uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b" +version = "0.5.0" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[deps.Blosc_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Lz4_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "ef12cdd1c7fb7e1dfd6fa8fd60d4db6bc61d2f23" +uuid = "0b7ba130-8d10-5ba8-a3d6-c5182647fed9" +version = "1.21.6+2" + +[[deps.Bzip2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1b96ea4a01afe0ea4090c5c8039690672dd13f2e" +uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" +version = "1.0.9+0" + +[[deps.CEnum]] +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.5.0" + +[[deps.CFTime]] +deps = ["Dates", "Printf"] +git-tree-sha1 = "937628bf8b377208ac359f57314fd85d3e0165d9" +uuid = "179af706-886a-5703-950a-314cd64e0468" +version = "0.1.4" + +[[deps.CRC32c]] +uuid = "8bf52ea8-c179-5cab-976a-9e18b702a9bc" + +[[deps.CRlibm]] +deps = ["CRlibm_jll"] +git-tree-sha1 = "32abd86e3c2025db5172aa182b982debed519834" +uuid = "96374032-68de-5a5b-8d9e-752f78720389" +version = "1.0.1" + +[[deps.CRlibm_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "e329286945d0cfc04456972ea732551869af1cfc" +uuid = "4e9b3aee-d8a1-5a3d-ad8b-7d824db253f0" +version = "1.0.1+0" + +[[deps.CUDA]] +deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "Crayons", "DataFrames", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LLVMLoopInfo", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "NVTX", "Preferences", "PrettyTables", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "StaticArrays", "Statistics", "demumble_jll"] +git-tree-sha1 = "7be665c420b5d16059b1ba00b1dbb4e85012fa65" +uuid = "052768ef-5323-5732-b1bb-66c8b64840ba" +version = "5.6.1" + + [deps.CUDA.extensions] + ChainRulesCoreExt = "ChainRulesCore" + EnzymeCoreExt = "EnzymeCore" + SpecialFunctionsExt = "SpecialFunctions" + + [deps.CUDA.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" + +[[deps.CUDA_Driver_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "14996d716a2eaaeccfc8d7bc854dd87fde720ac1" +uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc" +version = "0.10.4+0" + +[[deps.CUDA_Runtime_Discovery]] +deps = ["Libdl"] +git-tree-sha1 = "33576c7c1b2500f8e7e6baa082e04563203b3a45" +uuid = "1af6417a-86b4-443c-805f-a4643ffb695f" +version = "0.3.5" + +[[deps.CUDA_Runtime_jll]] +deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "17f1536c600133f7c4113bae0a2d98dbf27c7ebc" +uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2" +version = "0.15.5+0" + +[[deps.Cairo_jll]] +deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "009060c9a6168704143100f36ab08f06c2af4642" +uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a" +version = "1.18.2+1" + +[[deps.ChainRulesCore]] +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "1713c74e00545bfe14605d2a2be1712de8fbcb58" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "1.25.1" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" + +[[deps.ColorBrewer]] +deps = ["Colors", "JSON"] +git-tree-sha1 = "e771a63cc8b539eca78c85b0cabd9233d6c8f06f" +uuid = "a2cac450-b92f-5266-8821-25eda20663c8" +version = "0.4.1" + +[[deps.ColorSchemes]] +deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] +git-tree-sha1 = "403f2d8e209681fcbd9468a8514efff3ea08452e" +uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +version = "3.29.0" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "c7acce7a7e1078a20a285211dd73cd3941a871d6" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.12.0" + + [deps.ColorTypes.extensions] + StyledStringsExt = "StyledStrings" + + [deps.ColorTypes.weakdeps] + StyledStrings = "f489334b-da3d-4c2e-b8f0-e476e12c162b" + +[[deps.ColorVectorSpace]] +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "8b3b6f87ce8f65a2b4f857528fd8d70086cd72b1" +uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" +version = "0.11.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "64e15186f0aa277e174aa81798f7eb8598e0157e" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.13.0" + +[[deps.CommonDataModel]] +deps = ["CFTime", "DataStructures", "Dates", "Preferences", "Printf", "Statistics"] +git-tree-sha1 = "98d64d5b9e5263884276656a43c45424b3a645c2" +uuid = "1fbeeb36-5f17-413c-809b-666fb144f157" +version = "0.3.7" + +[[deps.Compat]] +deps = ["TOML", "UUIDs"] +git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.16.0" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.1.1+0" + +[[deps.CompoundPeriods]] +deps = ["Dates"] +git-tree-sha1 = "147d988f6a91fcdd5c07a86b52eb774803477326" +uuid = "a216cea6-0a8c-5945-ab87-5ade47210022" +version = "0.5.4" + +[[deps.ConstructionBase]] +git-tree-sha1 = "76219f1ed5771adbb096743bff43fb5fdd4c1157" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.5.8" +weakdeps = ["IntervalSets", "LinearAlgebra", "StaticArrays"] + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseLinearAlgebraExt = "LinearAlgebra" + ConstructionBaseStaticArraysExt = "StaticArrays" + +[[deps.Contour]] +git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8" +uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" +version = "0.6.3" + +[[deps.Crayons]] +git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.1.1" + +[[deps.CubedSphere]] +deps = ["TaylorSeries"] +git-tree-sha1 = "10874d1500159336863decaef665ab54805be29c" +uuid = "7445602f-e544-4518-8976-18f8e8ae6cdb" +version = "0.3.1" + +[[deps.DataAPI]] +git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.16.0" + +[[deps.DataFrames]] +deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "fb61b4812c49343d7ef0b533ba982c46021938a6" +uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +version = "1.7.0" + +[[deps.DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.20" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[deps.Dbus_jll]] +deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "fc173b380865f70627d7dd1190dc2fce6cc105af" +uuid = "ee1fde0b-3d02-5ea6-8484-8dfef6360eab" +version = "1.14.10+0" + +[[deps.DelaunayTriangulation]] +deps = ["AdaptivePredicates", "EnumX", "ExactPredicates", "Random"] +git-tree-sha1 = "5620ff4ee0084a6ab7097a27ba0c19290200b037" +uuid = "927a84f5-c5f4-47a5-9785-b46e178433df" +version = "1.6.4" + +[[deps.DiskArrays]] +deps = ["LRUCache", "Mmap", "OffsetArrays"] +git-tree-sha1 = "5109a9314f8904f96a14b80d40dce5c9972c584f" +uuid = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" +version = "0.4.10" + +[[deps.Distances]] +deps = ["LinearAlgebra", "Statistics", "StatsAPI"] +git-tree-sha1 = "c7e3a542b999843086e2f29dac96a618c105be1d" +uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" +version = "0.10.12" +weakdeps = ["ChainRulesCore", "SparseArrays"] + + [deps.Distances.extensions] + DistancesChainRulesCoreExt = "ChainRulesCore" + DistancesSparseArraysExt = "SparseArrays" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[deps.Distributions]] +deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "03aa5d44647eaec98e1920635cdfed5d5560a8b9" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.25.117" + + [deps.Distributions.extensions] + DistributionsChainRulesCoreExt = "ChainRulesCore" + DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsTestExt = "Test" + + [deps.Distributions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.EarCut_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "e3290f2d49e661fbd94046d7e3726ffcb2d41053" +uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5" +version = "2.2.4+0" + +[[deps.EnumX]] +git-tree-sha1 = "bdb1942cd4c45e3c678fd11569d5cccd80976237" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.4" + +[[deps.EpollShim_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8a4be429317c42cfae6a7fc03c31bad1970c310d" +uuid = "2702e6a9-849d-5ed8-8c21-79e8b8f9ee43" +version = "0.0.20230411+1" + +[[deps.ErrorfreeArithmetic]] +git-tree-sha1 = "d6863c556f1142a061532e79f611aa46be201686" +uuid = "90fa49ef-747e-5e6f-a989-263ba693cf1a" +version = "0.5.2" + +[[deps.ExactPredicates]] +deps = ["IntervalArithmetic", "Random", "StaticArraysCore", "Test"] +git-tree-sha1 = "276e83bc8b21589b79303b9985c321024ffdf59c" +uuid = "429591f6-91af-11e9-00e2-59fbe8cec110" +version = "2.2.5" + +[[deps.Expat_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d55dffd9ae73ff72f1c0482454dcf2ec6c6c4a63" +uuid = "2e619515-83b5-522b-bb60-26c02a35a201" +version = "2.6.5+0" + +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + +[[deps.Extents]] +git-tree-sha1 = "063512a13dbe9c40d999c439268539aa552d1ae6" +uuid = "411431e0-e8b7-467b-b5e0-f676ba4f2910" +version = "0.1.5" + +[[deps.FFMPEG_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] +git-tree-sha1 = "8cc47f299902e13f90405ddb5bf87e5d474c0d38" +uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" +version = "6.1.2+0" + +[[deps.FFTW]] +deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"] +git-tree-sha1 = "7de7c78d681078f027389e067864a8d53bd7c3c9" +uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" +version = "1.8.1" + +[[deps.FFTW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4d81ed14783ec49ce9f2e168208a12ce1815aa25" +uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a" +version = "3.3.10+3" + +[[deps.FastRounding]] +deps = ["ErrorfreeArithmetic", "LinearAlgebra"] +git-tree-sha1 = "6344aa18f654196be82e62816935225b3b9abe44" +uuid = "fa42c844-2597-5d31-933b-ebd51ab2693f" +version = "0.3.1" + +[[deps.FileIO]] +deps = ["Pkg", "Requires", "UUIDs"] +git-tree-sha1 = "2dd20384bf8c6d411b5c7370865b1e9b26cb2ea3" +uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +version = "1.16.6" + + [deps.FileIO.extensions] + HTTPExt = "HTTP" + + [deps.FileIO.weakdeps] + HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" + +[[deps.FilePaths]] +deps = ["FilePathsBase", "MacroTools", "Reexport", "Requires"] +git-tree-sha1 = "919d9412dbf53a2e6fe74af62a73ceed0bce0629" +uuid = "8fc22ac5-c921-52a6-82fd-178b2807b824" +version = "0.8.3" + +[[deps.FilePathsBase]] +deps = ["Compat", "Dates"] +git-tree-sha1 = "2ec417fc319faa2d768621085cc1feebbdee686b" +uuid = "48062228-2e41-5def-b9a4-89aafe57970f" +version = "0.9.23" +weakdeps = ["Mmap", "Test"] + + [deps.FilePathsBase.extensions] + FilePathsBaseMmapExt = "Mmap" + FilePathsBaseTestExt = "Test" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" + +[[deps.FillArrays]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "6a70198746448456524cb442b8af316927ff3e1a" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.13.0" +weakdeps = ["PDMats", "SparseArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.5" + +[[deps.Fontconfig_jll]] +deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Zlib_jll"] +git-tree-sha1 = "21fac3c77d7b5a9fc03b0ec503aa1a6392c34d2b" +uuid = "a3f928ae-7b40-5064-980b-68af3947d34b" +version = "2.15.0+0" + +[[deps.Format]] +git-tree-sha1 = "9c68794ef81b08086aeb32eeaf33531668d5f5fc" +uuid = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8" +version = "1.3.7" + +[[deps.FreeType]] +deps = ["CEnum", "FreeType2_jll"] +git-tree-sha1 = "907369da0f8e80728ab49c1c7e09327bf0d6d999" +uuid = "b38be410-82b0-50bf-ab77-7b57e271db43" +version = "4.1.1" + +[[deps.FreeType2_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "786e968a8d2fb167f2e4880baba62e0e26bd8e4e" +uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" +version = "2.13.3+1" + +[[deps.FreeTypeAbstraction]] +deps = ["ColorVectorSpace", "Colors", "FreeType", "GeometryBasics"] +git-tree-sha1 = "d52e255138ac21be31fa633200b65e4e71d26802" +uuid = "663a7486-cb36-511b-a19d-713bb74d65c9" +version = "0.10.6" + +[[deps.FriBidi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "846f7026a9decf3679419122b49f8a1fdb48d2d5" +uuid = "559328eb-81f9-559d-9380-de523a88c83c" +version = "1.0.16+0" + +[[deps.Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" + +[[deps.GLFW]] +deps = ["GLFW_jll"] +git-tree-sha1 = "7ed24cfc4cb29fb10c0e8cca871ddff54c32a4c3" +uuid = "f7f18e0c-5ee9-5ccd-a5bf-e8befd85ed98" +version = "3.4.3" + +[[deps.GLFW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll", "libdecor_jll", "xkbcommon_jll"] +git-tree-sha1 = "fcb0584ff34e25155876418979d4c8971243bb89" +uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89" +version = "3.4.0+2" + +[[deps.GLMakie]] +deps = ["ColorTypes", "Colors", "FileIO", "FixedPointNumbers", "FreeTypeAbstraction", "GLFW", "GeometryBasics", "LinearAlgebra", "Makie", "Markdown", "MeshIO", "ModernGL", "Observables", "PrecompileTools", "Printf", "ShaderAbstractions", "StaticArrays"] +git-tree-sha1 = "487ffeede54553565023a107529434ff585060ae" +uuid = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" +version = "0.11.2" + +[[deps.GPUArrays]] +deps = ["Adapt", "GPUArraysCore", "KernelAbstractions", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "ScopedValues", "Serialization", "Statistics"] +git-tree-sha1 = "eea7b3a1964b4de269bb380462a9da604be7fcdb" +uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7" +version = "11.2.2" + +[[deps.GPUArraysCore]] +deps = ["Adapt"] +git-tree-sha1 = "83cf05ab16a73219e5f6bd1bdfa9848fa24ac627" +uuid = "46192b85-c4d5-4398-a991-12ede77f4527" +version = "0.2.0" + +[[deps.GPUCompiler]] +deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "PrecompileTools", "Preferences", "Scratch", "Serialization", "TOML", "TimerOutputs", "UUIDs"] +git-tree-sha1 = "199f213e40a7982e9138bc9edc3299419d510390" +uuid = "61eb1bfa-7361-4325-ad38-22787b887f55" +version = "1.2.0" + +[[deps.GeoFormatTypes]] +git-tree-sha1 = "8e233d5167e63d708d41f87597433f59a0f213fe" +uuid = "68eda718-8dee-11e9-39e7-89f7f65f511f" +version = "0.4.4" + +[[deps.GeoInterface]] +deps = ["DataAPI", "Extents", "GeoFormatTypes"] +git-tree-sha1 = "294e99f19869d0b0cb71aef92f19d03649d028d5" +uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +version = "1.4.1" + +[[deps.GeometryBasics]] +deps = ["EarCut_jll", "Extents", "GeoInterface", "IterTools", "LinearAlgebra", "PrecompileTools", "Random", "StaticArrays"] +git-tree-sha1 = "3ba0e2818cc2ff79a5989d4dca4bc63120a98bd9" +uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326" +version = "0.5.5" + +[[deps.Gettext_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046" +uuid = "78b55507-aeef-58d4-861c-77aaff3498b1" +version = "0.21.0+0" + +[[deps.Giflib_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6570366d757b50fabae9f4315ad74d2e40c0560a" +uuid = "59f7168a-df46-5410-90c8-f2779963d0ec" +version = "5.2.3+0" + +[[deps.Glib_jll]] +deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Zlib_jll"] +git-tree-sha1 = "b0036b392358c80d2d2124746c2bf3d48d457938" +uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" +version = "2.82.4+0" + +[[deps.Glob]] +git-tree-sha1 = "97285bbd5230dd766e9ef6749b80fc617126d496" +uuid = "c27321d9-0574-5035-807b-f59d2c89b15c" +version = "1.3.1" + +[[deps.Graphite2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "01979f9b37367603e2848ea225918a3b3861b606" +uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472" +version = "1.3.14+1" + +[[deps.GridLayoutBase]] +deps = ["GeometryBasics", "InteractiveUtils", "Observables"] +git-tree-sha1 = "dc6bed05c15523624909b3953686c5f5ffa10adc" +uuid = "3955a311-db13-416c-9275-1d80ed98e5e9" +version = "0.11.1" + +[[deps.Grisu]] +git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2" +uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe" +version = "1.0.2" + +[[deps.HDF5_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "LazyArtifacts", "LibCURL_jll", "Libdl", "MPICH_jll", "MPIPreferences", "MPItrampoline_jll", "MicrosoftMPI_jll", "OpenMPI_jll", "OpenSSL_jll", "TOML", "Zlib_jll", "libaec_jll"] +git-tree-sha1 = "38c8874692d48d5440d5752d6c74b0c6b0b60739" +uuid = "0234f1f7-429e-5d53-9886-15a909be8d59" +version = "1.14.2+1" + +[[deps.HarfBuzz_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll"] +git-tree-sha1 = "55c53be97790242c29031e5cd45e8ac296dadda3" +uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566" +version = "8.5.0+0" + +[[deps.HashArrayMappedTries]] +git-tree-sha1 = "2eaa69a7cab70a52b9687c8bf950a5a93ec895ae" +uuid = "076d061b-32b6-4027-95e0-9a2c6f6d7e74" +version = "0.2.0" + +[[deps.Hwloc_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "f93a9ce66cd89c9ba7a4695a47fd93b4c6bc59fa" +uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" +version = "2.12.0+0" + +[[deps.HypergeometricFunctions]] +deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] +git-tree-sha1 = "2bd56245074fab4015b9174f24ceba8293209053" +uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" +version = "0.3.27" + +[[deps.ImageAxes]] +deps = ["AxisArrays", "ImageBase", "ImageCore", "Reexport", "SimpleTraits"] +git-tree-sha1 = "e12629406c6c4442539436581041d372d69c55ba" +uuid = "2803e5a7-5153-5ecf-9a86-9b4c37f5f5ac" +version = "0.6.12" + +[[deps.ImageBase]] +deps = ["ImageCore", "Reexport"] +git-tree-sha1 = "eb49b82c172811fd2c86759fa0553a2221feb909" +uuid = "c817782e-172a-44cc-b673-b171935fbb9e" +version = "0.1.7" + +[[deps.ImageCore]] +deps = ["ColorVectorSpace", "Colors", "FixedPointNumbers", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "PrecompileTools", "Reexport"] +git-tree-sha1 = "8c193230235bbcee22c8066b0374f63b5683c2d3" +uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534" +version = "0.10.5" + +[[deps.ImageIO]] +deps = ["FileIO", "IndirectArrays", "JpegTurbo", "LazyModules", "Netpbm", "OpenEXR", "PNGFiles", "QOI", "Sixel", "TiffImages", "UUIDs", "WebP"] +git-tree-sha1 = "696144904b76e1ca433b886b4e7edd067d76cbf7" +uuid = "82e4d734-157c-48bb-816b-45c225c6df19" +version = "0.6.9" + +[[deps.ImageMetadata]] +deps = ["AxisArrays", "ImageAxes", "ImageBase", "ImageCore"] +git-tree-sha1 = "2a81c3897be6fbcde0802a0ebe6796d0562f63ec" +uuid = "bc367c6b-8a6b-528e-b4bd-a4b897500b49" +version = "0.9.10" + +[[deps.Imath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "0936ba688c6d201805a83da835b55c61a180db52" +uuid = "905a6f67-0a94-5f89-b386-d35d92009cd1" +version = "3.1.11+0" + +[[deps.IncompleteLU]] +deps = ["LinearAlgebra", "SparseArrays"] +git-tree-sha1 = "6c676e79f98abb6d33fa28122cad099f1e464afe" +uuid = "40713840-3770-5561-ab4c-a76e7d0d7895" +version = "0.2.1" + +[[deps.IndirectArrays]] +git-tree-sha1 = "012e604e1c7458645cb8b436f8fba789a51b257f" +uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959" +version = "1.0.0" + +[[deps.Inflate]] +git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d" +uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" +version = "0.1.5" + +[[deps.InlineStrings]] +git-tree-sha1 = "6a9fde685a7ac1eb3495f8e812c5a7c3711c2d5e" +uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" +version = "1.4.3" + + [deps.InlineStrings.extensions] + ArrowTypesExt = "ArrowTypes" + ParsersExt = "Parsers" + + [deps.InlineStrings.weakdeps] + ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" + Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" + +[[deps.IntelOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"] +git-tree-sha1 = "0f14a5456bdc6b9731a5682f439a672750a09e48" +uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" +version = "2025.0.4+0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[deps.Interpolations]] +deps = ["Adapt", "AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"] +git-tree-sha1 = "88a101217d7cb38a7b481ccd50d21876e1d1b0e0" +uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" +version = "0.15.1" +weakdeps = ["Unitful"] + + [deps.Interpolations.extensions] + InterpolationsUnitfulExt = "Unitful" + +[[deps.IntervalArithmetic]] +deps = ["CRlibm", "FastRounding", "LinearAlgebra", "Markdown", "Random", "RecipesBase", "RoundingEmulator", "SetRounding", "StaticArrays"] +git-tree-sha1 = "5ab7744289be503d76a944784bac3f2df7b809af" +uuid = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" +version = "0.20.9" + +[[deps.IntervalSets]] +git-tree-sha1 = "dba9ddf07f77f60450fe5d2e2beb9854d9a49bd0" +uuid = "8197267c-284f-5f27-9208-e0e47529a953" +version = "0.7.10" +weakdeps = ["Random", "RecipesBase", "Statistics"] + + [deps.IntervalSets.extensions] + IntervalSetsRandomExt = "Random" + IntervalSetsRecipesBaseExt = "RecipesBase" + IntervalSetsStatisticsExt = "Statistics" + +[[deps.InverseFunctions]] +git-tree-sha1 = "a779299d77cd080bf77b97535acecd73e1c5e5cb" +uuid = "3587e190-3f89-42d0-90ee-14403ec27112" +version = "0.1.17" +weakdeps = ["Dates", "Test"] + + [deps.InverseFunctions.extensions] + InverseFunctionsDatesExt = "Dates" + InverseFunctionsTestExt = "Test" + +[[deps.InvertedIndices]] +git-tree-sha1 = "6da3c4316095de0f5ee2ebd875df8721e7e0bdbe" +uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" +version = "1.3.1" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "e2222959fbc6c19554dc15174c81bf7bf3aa691c" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.4" + +[[deps.Isoband]] +deps = ["isoband_jll"] +git-tree-sha1 = "f9b6d97355599074dc867318950adaa6f9946137" +uuid = "f1662d9f-8043-43de-a69a-05efc1cc6ff4" +version = "0.1.1" + +[[deps.IterTools]] +git-tree-sha1 = "42d5f897009e7ff2cf88db414a389e5ed1bdd023" +uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" +version = "1.10.0" + +[[deps.IterativeSolvers]] +deps = ["LinearAlgebra", "Printf", "Random", "RecipesBase", "SparseArrays"] +git-tree-sha1 = "59545b0a2b27208b0650df0a46b8e3019f85055b" +uuid = "42fd0dbc-a981-5370-80f2-aaf504508153" +version = "0.9.4" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLD2]] +deps = ["FileIO", "MacroTools", "Mmap", "OrderedCollections", "PrecompileTools", "Requires", "TranscodingStreams"] +git-tree-sha1 = "91d501cb908df6f134352ad73cde5efc50138279" +uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819" +version = "0.5.11" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "a007feb38b422fbdab534406aeca1b86823cb4d6" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.7.0" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.JpegTurbo]] +deps = ["CEnum", "FileIO", "ImageCore", "JpegTurbo_jll", "TOML"] +git-tree-sha1 = "fa6d0bcff8583bac20f1ffa708c3913ca605c611" +uuid = "b835a17e-a41a-41e7-81f0-2f016b05efe0" +version = "0.1.5" + +[[deps.JpegTurbo_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "eac1206917768cb54957c65a615460d87b455fc1" +uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" +version = "3.1.1+0" + +[[deps.JuliaNVTXCallbacks_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "af433a10f3942e882d3c671aacb203e006a5808f" +uuid = "9c1d0b0a-7046-5b2e-a33f-ea22f176ac7e" +version = "0.2.1+0" + +[[deps.KernelAbstractions]] +deps = ["Adapt", "Atomix", "InteractiveUtils", "MacroTools", "PrecompileTools", "Requires", "StaticArrays", "UUIDs"] +git-tree-sha1 = "80d268b2f4e396edc5ea004d1e0f569231c71e9e" +uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c" +version = "0.9.34" + + [deps.KernelAbstractions.extensions] + EnzymeExt = "EnzymeCore" + LinearAlgebraExt = "LinearAlgebra" + SparseArraysExt = "SparseArrays" + + [deps.KernelAbstractions.weakdeps] + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[deps.KernelDensity]] +deps = ["Distributions", "DocStringExtensions", "FFTW", "Interpolations", "StatsBase"] +git-tree-sha1 = "7d703202e65efa1369de1279c162b915e245eed1" +uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b" +version = "0.6.9" + +[[deps.LAME_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "170b660facf5df5de098d866564877e119141cbd" +uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d" +version = "3.100.2+0" + +[[deps.LERC_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "aaafe88dccbd957a8d82f7d05be9b69172e0cee3" +uuid = "88015f11-f218-50d7-93a8-a6af411a945d" +version = "4.0.1+0" + +[[deps.LLVM]] +deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Preferences", "Printf", "Unicode"] +git-tree-sha1 = "5fcfea6df2ff3e4da708a40c969c3812162346df" +uuid = "929cbde3-209d-540e-8aea-75f648917ca0" +version = "9.2.0" +weakdeps = ["BFloat16s"] + + [deps.LLVM.extensions] + BFloat16sExt = "BFloat16s" + +[[deps.LLVMExtra_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] +git-tree-sha1 = "4b5ad6a4ffa91a00050a964492bc4f86bb48cea0" +uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" +version = "0.0.35+0" + +[[deps.LLVMLoopInfo]] +git-tree-sha1 = "2e5c102cfc41f48ae4740c7eca7743cc7e7b75ea" +uuid = "8b046642-f1f6-4319-8d3c-209ddc03c586" +version = "1.0.0" + +[[deps.LLVMOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "78211fb6cbc872f77cad3fc0b6cf647d923f4929" +uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" +version = "18.1.7+0" + +[[deps.LRUCache]] +git-tree-sha1 = "b3cc6698599b10e652832c2f23db3cab99d51b59" +uuid = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" +version = "1.6.1" +weakdeps = ["Serialization"] + + [deps.LRUCache.extensions] + SerializationExt = ["Serialization"] + +[[deps.LZO_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1c602b1127f4751facb671441ca72715cc95938a" +uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac" +version = "2.10.3+0" + +[[deps.LaTeXStrings]] +git-tree-sha1 = "dda21b8cbd6a6c40d9d02a73230f9d70fed6918c" +uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +version = "1.4.0" + +[[deps.LazyArtifacts]] +deps = ["Artifacts", "Pkg"] +uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" + +[[deps.LazyModules]] +git-tree-sha1 = "a560dd966b386ac9ae60bdd3a3d3a326062d3c3e" +uuid = "8cdb02fc-e678-4876-92c5-9defec4f444e" +version = "0.3.1" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.4.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[deps.Libffi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "27ecae93dd25ee0909666e6835051dd684cc035e" +uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490" +version = "3.2.2+2" + +[[deps.Libgcrypt_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll"] +git-tree-sha1 = "8be878062e0ffa2c3f67bb58a595375eda5de80b" +uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4" +version = "1.11.0+0" + +[[deps.Libglvnd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll", "Xorg_libXext_jll"] +git-tree-sha1 = "ff3b4b9d35de638936a525ecd36e86a8bb919d11" +uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29" +version = "1.7.0+0" + +[[deps.Libgpg_error_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "df37206100d39f79b3376afb6b9cee4970041c61" +uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8" +version = "1.51.1+0" + +[[deps.Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "be484f5c92fad0bd8acfef35fe017900b0b73809" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.18.0+0" + +[[deps.Libmount_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "89211ea35d9df5831fca5d33552c02bd33878419" +uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" +version = "2.40.3+0" + +[[deps.Libtiff_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "4ab7581296671007fc33f07a721631b8855f4b1d" +uuid = "89763e89-9b03-5906-acba-b20f662cd828" +version = "4.7.1+0" + +[[deps.Libuuid_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e888ad02ce716b319e6bdb985d2ef300e7089889" +uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700" +version = "2.40.3+0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "13ca9e2586b89836fd20cccf56e57e2b9ae7f38f" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.3.29" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[deps.Lz4_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "191686b1ac1ea9c89fc52e996ad15d1d241d1e33" +uuid = "5ced341a-0733-55b8-9ab6-a4889d929147" +version = "1.10.1+0" + +[[deps.MKL_jll]] +deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "oneTBB_jll"] +git-tree-sha1 = "5de60bc6cb3899cd318d80d627560fae2e2d99ae" +uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" +version = "2025.0.1+1" + +[[deps.MPI]] +deps = ["Distributed", "DocStringExtensions", "Libdl", "MPICH_jll", "MPIPreferences", "MPItrampoline_jll", "MicrosoftMPI_jll", "OpenMPI_jll", "PkgVersion", "PrecompileTools", "Requires", "Serialization", "Sockets"] +git-tree-sha1 = "892676019c58f34e38743bc989b0eca5bce5edc5" +uuid = "da04e1cc-30fd-572f-bb4f-1f8673147195" +version = "0.20.22" + + [deps.MPI.extensions] + AMDGPUExt = "AMDGPU" + CUDAExt = "CUDA" + + [deps.MPI.weakdeps] + AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + +[[deps.MPICH_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "e7159031670cee777cc2840aef7a521c3603e36c" +uuid = "7cb0a576-ebde-5e09-9194-50597f1243b4" +version = "4.3.0+0" + +[[deps.MPIPreferences]] +deps = ["Libdl", "Preferences"] +git-tree-sha1 = "c105fe467859e7f6e9a852cb15cb4301126fac07" +uuid = "3da0fdf6-3ccc-4f1b-acd9-58baa6c99267" +version = "0.1.11" + +[[deps.MPItrampoline_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] +git-tree-sha1 = "97aac4a518b6f01851f8821272780e1ba56fe90d" +uuid = "f1f71cc9-e9ae-5b93-9b94-4fe0e1ad3748" +version = "5.5.2+0" + +[[deps.MacroTools]] +git-tree-sha1 = "72aebe0b5051e5143a079a4685a46da330a40472" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.15" + +[[deps.Makie]] +deps = ["Animations", "Base64", "CRC32c", "ColorBrewer", "ColorSchemes", "ColorTypes", "Colors", "Contour", "Dates", "DelaunayTriangulation", "Distributions", "DocStringExtensions", "Downloads", "FFMPEG_jll", "FileIO", "FilePaths", "FixedPointNumbers", "Format", "FreeType", "FreeTypeAbstraction", "GeometryBasics", "GridLayoutBase", "ImageBase", "ImageIO", "InteractiveUtils", "Interpolations", "IntervalSets", "InverseFunctions", "Isoband", "KernelDensity", "LaTeXStrings", "LinearAlgebra", "MacroTools", "MakieCore", "Markdown", "MathTeXEngine", "Observables", "OffsetArrays", "PNGFiles", "Packing", "PlotUtils", "PolygonOps", "PrecompileTools", "Printf", "REPL", "Random", "RelocatableFolders", "Scratch", "ShaderAbstractions", "Showoff", "SignedDistanceFields", "SparseArrays", "Statistics", "StatsBase", "StatsFuns", "StructArrays", "TriplotBase", "UnicodeFun", "Unitful"] +git-tree-sha1 = "9680336a5b67f9f9f6eaa018f426043a8cd68200" +uuid = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" +version = "0.22.1" + +[[deps.MakieCore]] +deps = ["ColorTypes", "GeometryBasics", "IntervalSets", "Observables"] +git-tree-sha1 = "c731269d5a2c85ffdc689127a9ba6d73e978a4b1" +uuid = "20f20a25-4f0e-4fdf-b5d1-57303727442b" +version = "0.9.0" + +[[deps.MappedArrays]] +git-tree-sha1 = "2dab0221fe2b0f2cb6754eaa743cc266339f527e" +uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900" +version = "0.4.2" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[deps.MathTeXEngine]] +deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "UnicodeFun"] +git-tree-sha1 = "f45c8916e8385976e1ccd055c9874560c257ab13" +uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53" +version = "0.6.2" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.2+1" + +[[deps.MeshIO]] +deps = ["ColorTypes", "FileIO", "GeometryBasics", "Printf"] +git-tree-sha1 = "0644638417afafeceab065fc96ba5590538f966f" +uuid = "7269a6da-0436-5bbc-96c2-40638cbb6118" +version = "0.5.2" + +[[deps.MicrosoftMPI_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "bc95bf4149bf535c09602e3acdf950d9b4376227" +uuid = "9237b28f-5490-5468-be7b-bb81f5f5e6cf" +version = "10.1.4+3" + +[[deps.Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.2.0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[deps.Mocking]] +deps = ["Compat", "ExprTools"] +git-tree-sha1 = "2c140d60d7cb82badf06d8783800d0bcd1a7daa2" +uuid = "78c3b35d-d492-501b-9361-3d52fe80e533" +version = "0.8.1" + +[[deps.ModernGL]] +deps = ["Libdl"] +git-tree-sha1 = "ac6cb1d8807a05cf1acc9680e09d2294f9d33956" +uuid = "66fc600b-dfda-50eb-8b99-91cfa97b1301" +version = "1.1.8" + +[[deps.MosaicViews]] +deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"] +git-tree-sha1 = "7b86a5d4d70a9f5cdf2dacb3cbe6d251d1a61dbe" +uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389" +version = "0.3.4" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.1.10" + +[[deps.NCDatasets]] +deps = ["CFTime", "CommonDataModel", "DataStructures", "Dates", "DiskArrays", "NetCDF_jll", "NetworkOptions", "Printf"] +git-tree-sha1 = "2c9dc92001ac06d432f363f37ff5552954d9947c" +uuid = "85f8d34a-cbdd-5861-8df4-14fed0d494ab" +version = "0.14.6" + +[[deps.NVTX]] +deps = ["Colors", "JuliaNVTXCallbacks_jll", "Libdl", "NVTX_jll"] +git-tree-sha1 = "6a6f8bfaa91bb2e40ff562ab9f30dc827741daef" +uuid = "5da4648a-3479-48b8-97b9-01cb529c0a1f" +version = "0.3.5" + +[[deps.NVTX_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "2c7b791c1eba364e4a70aabdea4ddc1f5ca53911" +uuid = "e98f9f5b-d649-5603-91fd-7774390e6439" +version = "3.1.1+0" + +[[deps.NetCDF_jll]] +deps = ["Artifacts", "Blosc_jll", "Bzip2_jll", "HDF5_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "OpenMPI_jll", "XML2_jll", "Zlib_jll", "Zstd_jll", "libzip_jll"] +git-tree-sha1 = "a8af1798e4eb9ff768ce7fdefc0e957097793f15" +uuid = "7243133f-43d8-5620-bbf4-c2c921802cf3" +version = "400.902.209+0" + +[[deps.Netpbm]] +deps = ["FileIO", "ImageCore", "ImageMetadata"] +git-tree-sha1 = "d92b107dbb887293622df7697a2223f9f8176fcd" +uuid = "f09324ee-3d7c-5217-9330-fc30815ba969" +version = "1.1.1" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.Observables]] +git-tree-sha1 = "7438a59546cf62428fc9d1bc94729146d37a7225" +uuid = "510215fc-4207-5dde-b226-833fc4488ee2" +version = "0.5.5" + +[[deps.Oceananigans]] +deps = ["Adapt", "CUDA", "Crayons", "CubedSphere", "Dates", "Distances", "DocStringExtensions", "FFTW", "GPUArrays", "Glob", "IncompleteLU", "InteractiveUtils", "IterativeSolvers", "JLD2", "KernelAbstractions", "LinearAlgebra", "Logging", "MPI", "NCDatasets", "OffsetArrays", "OrderedCollections", "Pkg", "Printf", "Random", "Rotations", "SeawaterPolynomials", "SparseArrays", "StaticArrays", "Statistics", "StructArrays", "TimesDates"] +path = "../.." +uuid = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09" +version = "0.95.12" + + [deps.Oceananigans.extensions] + OceananigansEnzymeExt = "Enzyme" + OceananigansMakieExt = ["MakieCore", "Makie"] + OceananigansReactantExt = ["Reactant", "KernelAbstractions"] + + [deps.Oceananigans.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b" + Reactant = "3c362404-f566-11ee-1572-e11a4b42c853" + +[[deps.OffsetArrays]] +git-tree-sha1 = "5e1897147d1ff8d98883cda2be2187dcf57d8f0c" +uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +version = "1.15.0" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" + +[[deps.Ogg_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "887579a3eb005446d514ab7aeac5d1d027658b8f" +uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" +version = "1.3.5+1" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.23+4" + +[[deps.OpenEXR]] +deps = ["Colors", "FileIO", "OpenEXR_jll"] +git-tree-sha1 = "97db9e07fe2091882c765380ef58ec553074e9c7" +uuid = "52e1d378-f018-4a11-a4be-720524705ac7" +version = "0.3.3" + +[[deps.OpenEXR_jll]] +deps = ["Artifacts", "Imath_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "8292dd5c8a38257111ada2174000a33745b06d4e" +uuid = "18a262bb-aa17-5467-a713-aee519bc75cb" +version = "3.2.4+0" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.1+2" + +[[deps.OpenMPI_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML", "Zlib_jll"] +git-tree-sha1 = "6c1cf6181ffe0aa33eb33250ca2a60e54a15ea66" +uuid = "fe0851c0-eecd-5654-98d4-656369965a5c" +version = "5.0.7+0" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "a9697f1d06cc3eb3fb3ad49cc67f2cfabaac31ea" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.0.16+0" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1346c9208249809840c91b26703912dff463d335" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.6+0" + +[[deps.Opus_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6703a85cb3781bd5909d48730a67205f3f31a575" +uuid = "91d4177d-7536-5919-b921-800302f37372" +version = "1.3.3+0" + +[[deps.OrderedCollections]] +git-tree-sha1 = "cc4054e898b852042d7b503313f7ad03de99c3dd" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.8.0" + +[[deps.OrthogonalSphericalShellGrids]] +deps = ["Adapt", "Distances", "KernelAbstractions", "MPI", "Oceananigans", "OffsetArrays", "Statistics"] +git-tree-sha1 = "d11fd9caa8246493ca6da68bf00fef6a86bfa835" +uuid = "c2be9673-fb75-4747-82dc-aa2bb9f4aed0" +version = "0.2.1" + +[[deps.PCRE2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" +version = "10.42.0+1" + +[[deps.PDMats]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "966b85253e959ea89c53a9abebbf2e964fbf593b" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.11.32" + +[[deps.PNGFiles]] +deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"] +git-tree-sha1 = "cf181f0b1e6a18dfeb0ee8acc4a9d1672499626c" +uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883" +version = "0.4.4" + +[[deps.Packing]] +deps = ["GeometryBasics"] +git-tree-sha1 = "bc5bf2ea3d5351edf285a06b0016788a121ce92c" +uuid = "19eb6ba3-879d-56ad-ad62-d5c202156566" +version = "0.5.1" + +[[deps.PaddedViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "0fac6313486baae819364c52b4f483450a9d793f" +uuid = "5432bcbf-9aad-5242-b902-cca2824c8663" +version = "0.5.12" + +[[deps.Pango_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "3b31172c032a1def20c98dae3f2cdc9d10e3b561" +uuid = "36c8627f-9965-5494-a995-c6b170f724f3" +version = "1.56.1+0" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.8.1" + +[[deps.Pixman_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "Libdl"] +git-tree-sha1 = "35621f10a7531bc8fa58f74610b1bfb70a3cfc6b" +uuid = "30392449-352a-5448-841d-b1acce4e97dc" +version = "0.43.4+0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.10.0" + +[[deps.PkgVersion]] +deps = ["Pkg"] +git-tree-sha1 = "f9501cc0430a26bc3d156ae1b5b0c1b47af4d6da" +uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688" +version = "0.3.3" + +[[deps.PlotUtils]] +deps = ["ColorSchemes", "Colors", "Dates", "PrecompileTools", "Printf", "Random", "Reexport", "StableRNGs", "Statistics"] +git-tree-sha1 = "3ca9a356cd2e113c420f2c13bea19f8d3fb1cb18" +uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" +version = "1.4.3" + +[[deps.PolygonOps]] +git-tree-sha1 = "77b3d3605fc1cd0b42d95eba87dfcd2bf67d5ff6" +uuid = "647866c9-e3ac-4575-94e7-e3d426903924" +version = "0.1.2" + +[[deps.PooledArrays]] +deps = ["DataAPI", "Future"] +git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" +uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +version = "1.4.3" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.1" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.PrettyTables]] +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "1101cd475833706e4d0e7b122218257178f48f34" +uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +version = "2.4.0" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[deps.ProgressMeter]] +deps = ["Distributed", "Printf"] +git-tree-sha1 = "8f6bc219586aef8baf0ff9a5fe16ee9c70cb65e4" +uuid = "92933f4c-e287-5a05-a399-4b506db050ca" +version = "1.10.2" + +[[deps.PtrArrays]] +git-tree-sha1 = "1d36ef11a9aaf1e8b74dacc6a731dd1de8fd493d" +uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" +version = "1.3.0" + +[[deps.QOI]] +deps = ["ColorTypes", "FileIO", "FixedPointNumbers"] +git-tree-sha1 = "8b3fc30bc0390abdce15f8822c889f669baed73d" +uuid = "4b34888f-f399-49d4-9bb3-47ed5cae4e65" +version = "1.0.1" + +[[deps.QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "9da16da70037ba9d701192e27befedefb91ec284" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.11.2" + + [deps.QuadGK.extensions] + QuadGKEnzymeExt = "Enzyme" + + [deps.QuadGK.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + +[[deps.Quaternions]] +deps = ["LinearAlgebra", "Random", "RealDot"] +git-tree-sha1 = "994cc27cdacca10e68feb291673ec3a76aa2fae9" +uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" +version = "0.7.6" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[deps.Random123]] +deps = ["Random", "RandomNumbers"] +git-tree-sha1 = "4743b43e5a9c4a2ede372de7061eed81795b12e7" +uuid = "74087812-796a-5b5d-8853-05524746bad3" +version = "1.7.0" + +[[deps.RandomNumbers]] +deps = ["Random"] +git-tree-sha1 = "c6ec94d2aaba1ab2ff983052cf6a606ca5985902" +uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143" +version = "1.6.0" + +[[deps.RangeArrays]] +git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5" +uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d" +version = "0.3.2" + +[[deps.Ratios]] +deps = ["Requires"] +git-tree-sha1 = "1342a47bf3260ee108163042310d26f2be5ec90b" +uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" +version = "0.4.5" +weakdeps = ["FixedPointNumbers"] + + [deps.Ratios.extensions] + RatiosFixedPointNumbersExt = "FixedPointNumbers" + +[[deps.RealDot]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9" +uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" +version = "0.1.0" + +[[deps.RecipesBase]] +deps = ["PrecompileTools"] +git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.3.4" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.RelocatableFolders]] +deps = ["SHA", "Scratch"] +git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" +uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" +version = "1.0.1" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.0" + +[[deps.Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "852bd0f55565a9e973fcfee83a84413270224dc4" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.8.0" + +[[deps.Rmath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "58cdd8fb2201a6267e1db87ff148dd6c1dbd8ad8" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.5.1+0" + +[[deps.Rotations]] +deps = ["LinearAlgebra", "Quaternions", "Random", "StaticArrays"] +git-tree-sha1 = "5680a9276685d392c87407df00d57c9924d9f11e" +uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc" +version = "1.7.1" +weakdeps = ["RecipesBase"] + + [deps.Rotations.extensions] + RotationsRecipesBaseExt = "RecipesBase" + +[[deps.RoundingEmulator]] +git-tree-sha1 = "40b9edad2e5287e05bd413a38f61a8ff55b9557b" +uuid = "5eaf0fd0-dfba-4ccb-bf02-d820a40db705" +version = "0.2.1" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.SIMD]] +deps = ["PrecompileTools"] +git-tree-sha1 = "fea870727142270bdf7624ad675901a1ee3b4c87" +uuid = "fdea26ae-647d-5447-a871-4b548cad5224" +version = "3.7.1" + +[[deps.ScopedValues]] +deps = ["HashArrayMappedTries", "Logging"] +git-tree-sha1 = "1147f140b4c8ddab224c94efa9569fc23d63ab44" +uuid = "7e506255-f358-4e82-b7e4-beb19740aa63" +version = "1.3.0" + +[[deps.Scratch]] +deps = ["Dates"] +git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386" +uuid = "6c6a2e73-6563-6170-7368-637461726353" +version = "1.2.1" + +[[deps.SeawaterPolynomials]] +git-tree-sha1 = "78f965a2f0cd5250a20c9aba9979346dd2b35734" +uuid = "d496a93d-167e-4197-9f49-d3af4ff8fe40" +version = "0.3.5" + +[[deps.SentinelArrays]] +deps = ["Dates", "Random"] +git-tree-sha1 = "712fb0231ee6f9120e005ccd56297abbc053e7e0" +uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" +version = "1.4.8" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[deps.SetRounding]] +git-tree-sha1 = "d7a25e439d07a17b7cdf97eecee504c50fedf5f6" +uuid = "3cc68bcd-71a2-5612-b932-767ffbe40ab0" +version = "0.2.1" + +[[deps.ShaderAbstractions]] +deps = ["ColorTypes", "FixedPointNumbers", "GeometryBasics", "LinearAlgebra", "Observables", "StaticArrays"] +git-tree-sha1 = "818554664a2e01fc3784becb2eb3a82326a604b6" +uuid = "65257c39-d410-5151-9873-9b3e5be5013e" +version = "0.5.0" + +[[deps.SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + +[[deps.Showoff]] +deps = ["Dates", "Grisu"] +git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de" +uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f" +version = "1.0.3" + +[[deps.SignedDistanceFields]] +deps = ["Random", "Statistics", "Test"] +git-tree-sha1 = "d263a08ec505853a5ff1c1ebde2070419e3f28e9" +uuid = "73760f76-fbc4-59ce-8f25-708e95d2df96" +version = "0.4.0" + +[[deps.SimpleTraits]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" +uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +version = "0.9.4" + +[[deps.Sixel]] +deps = ["Dates", "FileIO", "ImageCore", "IndirectArrays", "OffsetArrays", "REPL", "libsixel_jll"] +git-tree-sha1 = "2da10356e31327c7096832eb9cd86307a50b1eb6" +uuid = "45858cf5-a6b0-47a3-bbea-62219f50df47" +version = "0.1.3" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[deps.SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.2.1" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.10.0" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "64cca0c26b4f31ba18f13f6c12af7c85f478cfde" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.5.0" +weakdeps = ["ChainRulesCore"] + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + +[[deps.StableRNGs]] +deps = ["Random"] +git-tree-sha1 = "83e6cce8324d49dfaf9ef059227f91ed4441a8e5" +uuid = "860ef19b-820b-49d6-a774-d7a799459cd3" +version = "1.0.2" + +[[deps.StackViews]] +deps = ["OffsetArrays"] +git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c" +uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15" +version = "0.1.1" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "e3be13f448a43610f978d29b7adf78c76022467a" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.9.12" +weakdeps = ["ChainRulesCore", "Statistics"] + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "192954ef1208c7019899fbf8049e717f92959682" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.3" + +[[deps.Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.10.0" + +[[deps.StatsAPI]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.7.0" + +[[deps.StatsBase]] +deps = ["AliasTables", "DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "29321314c920c26684834965ec2ce0dacc9cf8e5" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.34.4" + +[[deps.StatsFuns]] +deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] +git-tree-sha1 = "b423576adc27097764a90e163157bcfc9acf0f46" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "1.3.2" +weakdeps = ["ChainRulesCore", "InverseFunctions"] + + [deps.StatsFuns.extensions] + StatsFunsChainRulesCoreExt = "ChainRulesCore" + StatsFunsInverseFunctionsExt = "InverseFunctions" + +[[deps.StringManipulation]] +deps = ["PrecompileTools"] +git-tree-sha1 = "725421ae8e530ec29bcbdddbe91ff8053421d023" +uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" +version = "0.4.1" + +[[deps.StructArrays]] +deps = ["ConstructionBase", "DataAPI", "Tables"] +git-tree-sha1 = "5a3a31c41e15a1e042d60f2f4942adccba05d3c9" +uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +version = "0.7.0" +weakdeps = ["Adapt", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "SparseArrays", "StaticArrays"] + + [deps.StructArrays.extensions] + StructArraysAdaptExt = "Adapt" + StructArraysGPUArraysCoreExt = ["GPUArraysCore", "KernelAbstractions"] + StructArraysLinearAlgebraExt = "LinearAlgebra" + StructArraysSparseArraysExt = "SparseArrays" + StructArraysStaticArraysExt = "StaticArrays" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "7.2.1+1" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TZJData]] +deps = ["Artifacts"] +git-tree-sha1 = "7def47e953a91cdcebd08fbe76d69d2715499a7d" +uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" +version = "1.4.0+2025a" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.12.0" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.TaylorSeries]] +deps = ["LinearAlgebra", "Markdown", "Requires", "SparseArrays"] +git-tree-sha1 = "ae73e40c647c0061697fa9708ee12cce385653e3" +uuid = "6aa5eb33-94cf-58f4-a9d0-e4b2c4fc25ea" +version = "0.18.3" + + [deps.TaylorSeries.extensions] + TaylorSeriesIAExt = "IntervalArithmetic" + TaylorSeriesJLD2Ext = "JLD2" + TaylorSeriesRATExt = "RecursiveArrayTools" + TaylorSeriesSAExt = "StaticArrays" + + [deps.TaylorSeries.weakdeps] + IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" + JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819" + RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.TensorCore]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" +uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" +version = "0.1.1" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.TiffImages]] +deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "Mmap", "OffsetArrays", "PkgVersion", "ProgressMeter", "SIMD", "UUIDs"] +git-tree-sha1 = "f21231b166166bebc73b99cea236071eb047525b" +uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69" +version = "0.11.3" + +[[deps.TimeZones]] +deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] +git-tree-sha1 = "38bb1023fb94bfbaf2a29e1e0de4bbba6fe0bf6d" +uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" +version = "1.21.2" +weakdeps = ["RecipesBase"] + + [deps.TimeZones.extensions] + TimeZonesRecipesBaseExt = "RecipesBase" + +[[deps.TimerOutputs]] +deps = ["ExprTools", "Printf"] +git-tree-sha1 = "3832505b94c1868baea47764127e6d36b5c9f29e" +uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" +version = "0.5.27" + + [deps.TimerOutputs.extensions] + FlameGraphsExt = "FlameGraphs" + + [deps.TimerOutputs.weakdeps] + FlameGraphs = "08572546-2f56-4bcf-ba4e-bab62c3a3f89" + +[[deps.TimesDates]] +deps = ["CompoundPeriods", "Dates", "TimeZones"] +git-tree-sha1 = "4ca99fd8145f6ae574b6f98e1233148e7b91ac30" +uuid = "bdfc003b-8df8-5c39-adcd-3a9087f5df4a" +version = "0.3.1" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.11.3" + +[[deps.TriplotBase]] +git-tree-sha1 = "4d4ed7f294cda19382ff7de4c137d24d16adc89b" +uuid = "981d1d27-644d-49a2-9326-4793e63143c3" +version = "0.1.0" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[deps.UnicodeFun]] +deps = ["REPL"] +git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf" +uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1" +version = "0.4.1" + +[[deps.Unitful]] +deps = ["Dates", "LinearAlgebra", "Random"] +git-tree-sha1 = "c0667a8e676c53d390a09dc6870b3d8d6650e2bf" +uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" +version = "1.22.0" +weakdeps = ["ConstructionBase", "InverseFunctions"] + + [deps.Unitful.extensions] + ConstructionBaseUnitfulExt = "ConstructionBase" + InverseFunctionsUnitfulExt = "InverseFunctions" + +[[deps.UnsafeAtomics]] +git-tree-sha1 = "b13c4edda90890e5b04ba24e20a310fbe6f249ff" +uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f" +version = "0.3.0" +weakdeps = ["LLVM"] + + [deps.UnsafeAtomics.extensions] + UnsafeAtomicsLLVM = ["LLVM"] + +[[deps.Wayland_jll]] +deps = ["Artifacts", "EpollShim_jll", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "85c7811eddec9e7f22615371c3cc81a504c508ee" +uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89" +version = "1.21.0+2" + +[[deps.Wayland_protocols_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "5db3e9d307d32baba7067b13fc7b5aa6edd4a19a" +uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91" +version = "1.36.0+0" + +[[deps.WebP]] +deps = ["CEnum", "ColorTypes", "FileIO", "FixedPointNumbers", "ImageCore", "libwebp_jll"] +git-tree-sha1 = "aa1ca3c47f119fbdae8770c29820e5e6119b83f2" +uuid = "e3aaa7dc-3e4b-44e0-be63-ffb868ccd7c1" +version = "0.1.3" + +[[deps.WoodburyMatrices]] +deps = ["LinearAlgebra", "SparseArrays"] +git-tree-sha1 = "c1a7aa6219628fcd757dede0ca95e245c5cd9511" +uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6" +version = "1.0.0" + +[[deps.XML2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"] +git-tree-sha1 = "ee6f41aac16f6c9a8cab34e2f7a200418b1cc1e3" +uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" +version = "2.13.6+0" + +[[deps.XSLT_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "XML2_jll", "Zlib_jll"] +git-tree-sha1 = "7d1671acbe47ac88e981868a078bd6b4e27c5191" +uuid = "aed1982a-8fda-507f-9586-7b0439959a61" +version = "1.1.42+0" + +[[deps.XZ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "56c6604ec8b2d82cc4cfe01aa03b00426aac7e1f" +uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800" +version = "5.6.4+1" + +[[deps.Xorg_libX11_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] +git-tree-sha1 = "9dafcee1d24c4f024e7edc92603cedba72118283" +uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" +version = "1.8.6+3" + +[[deps.Xorg_libXau_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e9216fdcd8514b7072b43653874fd688e4c6c003" +uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" +version = "1.0.12+0" + +[[deps.Xorg_libXcursor_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"] +git-tree-sha1 = "807c226eaf3651e7b2c468f687ac788291f9a89b" +uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724" +version = "1.2.3+0" + +[[deps.Xorg_libXdmcp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "89799ae67c17caa5b3b5a19b8469eeee474377db" +uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" +version = "1.1.5+0" + +[[deps.Xorg_libXext_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "d7155fea91a4123ef59f42c4afb5ab3b4ca95058" +uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3" +version = "1.3.6+3" + +[[deps.Xorg_libXfixes_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "6fcc21d5aea1a0b7cce6cab3e62246abd1949b86" +uuid = "d091e8ba-531a-589c-9de9-94069b037ed8" +version = "6.0.0+0" + +[[deps.Xorg_libXi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libXext_jll", "Xorg_libXfixes_jll"] +git-tree-sha1 = "984b313b049c89739075b8e2a94407076de17449" +uuid = "a51aa0fd-4e3c-5386-b890-e753decda492" +version = "1.8.2+0" + +[[deps.Xorg_libXinerama_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libXext_jll"] +git-tree-sha1 = "a1a7eaf6c3b5b05cb903e35e8372049b107ac729" +uuid = "d1454406-59df-5ea1-beac-c340f2130bc3" +version = "1.1.5+0" + +[[deps.Xorg_libXrandr_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libXext_jll", "Xorg_libXrender_jll"] +git-tree-sha1 = "b6f664b7b2f6a39689d822a6300b14df4668f0f4" +uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484" +version = "1.5.4+0" + +[[deps.Xorg_libXrender_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "a490c6212a0e90d2d55111ac956f7c4fa9c277a6" +uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" +version = "0.9.11+1" + +[[deps.Xorg_libpthread_stubs_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "c57201109a9e4c0585b208bb408bc41d205ac4e9" +uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74" +version = "0.1.2+0" + +[[deps.Xorg_libxcb_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] +git-tree-sha1 = "1a74296303b6524a0472a8cb12d3d87a78eb3612" +uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" +version = "1.17.0+3" + +[[deps.Xorg_libxkbfile_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "dbc53e4cf7701c6c7047c51e17d6e64df55dca94" +uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a" +version = "1.1.2+1" + +[[deps.Xorg_xkbcomp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxkbfile_jll"] +git-tree-sha1 = "ab2221d309eda71020cdda67a973aa582aa85d69" +uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4" +version = "1.4.6+1" + +[[deps.Xorg_xkeyboard_config_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xkbcomp_jll"] +git-tree-sha1 = "691634e5453ad362044e2ad653e79f3ee3bb98c3" +uuid = "33bec58e-1273-512f-9401-5d533626f822" +version = "2.39.0+0" + +[[deps.Xorg_xtrans_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6dba04dbfb72ae3ebe5418ba33d087ba8aa8cb00" +uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" +version = "1.5.1+0" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "622cf78670d067c738667aaa96c553430b65e269" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.7+0" + +[[deps.demumble_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6498e3581023f8e530f34760d18f75a69e3a4ea8" +uuid = "1e29f10c-031c-5a83-9565-69cddfc27673" +version = "1.3.0+0" + +[[deps.isoband_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "51b5eeb3f98367157a7a12a1fb0aa5328946c03c" +uuid = "9a68df92-36a6-505f-a73e-abb412b6bfb4" +version = "0.2.3+0" + +[[deps.libaec_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "f5733a5a9047722470b95a81e1b172383971105c" +uuid = "477f73a3-ac25-53e9-8cc3-50b2fa2566f0" +version = "1.1.3+0" + +[[deps.libaom_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "522c1df09d05a71785765d19c9524661234738e9" +uuid = "a4ae2306-e953-59d6-aa16-d00cac43593b" +version = "3.11.0+0" + +[[deps.libass_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "e17c115d55c5fbb7e52ebedb427a0dca79d4484e" +uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0" +version = "0.15.2+0" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.11.0+0" + +[[deps.libdecor_jll]] +deps = ["Artifacts", "Dbus_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pango_jll", "Wayland_jll", "xkbcommon_jll"] +git-tree-sha1 = "9bf7903af251d2050b467f76bdbe57ce541f7f4f" +uuid = "1183f4f0-6f2a-5f1a-908b-139f9cdfea6f" +version = "0.2.2+0" + +[[deps.libfdk_aac_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8a22cf860a7d27e4f3498a0fe0811a7957badb38" +uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" +version = "2.0.3+0" + +[[deps.libpng_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "055a96774f383318750a1a5e10fd4151f04c29c5" +uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" +version = "1.6.46+0" + +[[deps.libsixel_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "libpng_jll"] +git-tree-sha1 = "c1733e347283df07689d71d61e14be986e49e47a" +uuid = "075b6546-f08a-558a-be8f-8157d0f608a5" +version = "1.10.5+0" + +[[deps.libvorbis_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"] +git-tree-sha1 = "490376214c4721cdaca654041f635213c6165cb3" +uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" +version = "1.3.7+2" + +[[deps.libwebp_jll]] +deps = ["Artifacts", "Giflib_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libglvnd_jll", "Libtiff_jll", "libpng_jll"] +git-tree-sha1 = "d2408cac540942921e7bd77272c32e58c33d8a77" +uuid = "c5f90fcd-3b7e-5836-afba-fc50a0988cb2" +version = "1.5.0+0" + +[[deps.libzip_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "OpenSSL_jll", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "86addc139bca85fdf9e7741e10977c45785727b7" +uuid = "337d8026-41b4-5cde-a456-74a10e5b31d1" +version = "1.11.3+0" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.52.0+1" + +[[deps.oneTBB_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d5a767a3bb77135a99e433afe0eb14cd7f6914c3" +uuid = "1317d2d5-d96f-522e-a858-c73665f53c3e" +version = "2022.0.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" + +[[deps.x264_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "14cc7083fc6dff3cc44f2bc435ee96d06ed79aa7" +uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a" +version = "10164.0.1+0" + +[[deps.x265_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "dcc541bb19ed5b0ede95581fb2e41ecf179527d2" +uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76" +version = "3.6.0+0" + +[[deps.xkbcommon_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"] +git-tree-sha1 = "63406453ed9b33a0df95d570816d5366c92b7809" +uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd" +version = "1.4.1+2" diff --git a/validation/orthogonal_spherical_shell_grid/Project.toml b/validation/orthogonal_spherical_shell_grid/Project.toml new file mode 100644 index 0000000000..a813b9ab26 --- /dev/null +++ b/validation/orthogonal_spherical_shell_grid/Project.toml @@ -0,0 +1,5 @@ +[deps] +GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" +Oceananigans = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09" +OrthogonalSphericalShellGrids = "c2be9673-fb75-4747-82dc-aa2bb9f4aed0" +StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" diff --git a/validation/orthogonal_spherical_shell_grid/polar_turbulence.jl b/validation/orthogonal_spherical_shell_grid/polar_turbulence.jl new file mode 100644 index 0000000000..7e23e59731 --- /dev/null +++ b/validation/orthogonal_spherical_shell_grid/polar_turbulence.jl @@ -0,0 +1,108 @@ +#= +using Oceananigans +using Oceananigans.Grids: RightConnected +using Oceananigans.OrthogonalSphericalShellGrids: RotatedLatitudeLongitudeGrid +using Oceananigans.OrthogonalSphericalShellGrids: rotate_coordinates +using Oceananigans.Units +using OrthogonalSphericalShellGrids: TripolarGrid +using Printf +using GLMakie + +Nx, Ny, Nz = 128, 128, 1 + +grid = RotatedLatitudeLongitudeGrid(size = (Nx, Ny, Nz), + latitude = (-60, 60), + longitude = (-60, 60), + north_pole = (0, 0), + halo = (7, 7, 3), + z = (-1000, 0), + topology = (Bounded, Bounded, Bounded)) + +model = HydrostaticFreeSurfaceModel(; grid, + coriolis = HydrostaticSphericalCoriolis(), + momentum_advection = WENOVectorInvariant()) + +U = 1 +ϵᵢ(λ, φ, z) = U * (2rand() - 1) +set!(model, u=ϵᵢ, v=ϵᵢ) + +Δx = minimum_xspacing(grid) +Δt = min(20minutes, 0.1 * Δx / U) +simulation = Simulation(model; Δt, stop_time=360days) + +progress_message(sim) = @printf("Iteration: %04d, time: %s, Δt: %s, wall time: %s\n", + iteration(sim), prettytime(sim), prettytime(sim.Δt), + prettytime(sim.run_wall_time)) + +simulation.callbacks[:progress] = Callback(progress_message, IterationInterval(100)) + +u, v, w = model.velocities +ζ = ∂x(v) - ∂y(u) +s = @at (Center, Center, Center) sqrt(u^2 + v^2) + +simulation.output_writers[:jld2] = JLD2OutputWriter(model, (; u, v, ζ, s), + schedule = TimeInterval(1day), + filename = "polar_turbulence", + overwrite_existing = true) + +@info "Run simulation..." + +run!(simulation) + +@info "Load output..." +=# + +filepath = simulation.output_writers[:jld2].filepath + +ζ_timeseries = FieldTimeSeries(filepath, "ζ") +u_timeseries = FieldTimeSeries(filepath, "u") +v_timeseries = FieldTimeSeries(filepath, "v") +s_timeseries = FieldTimeSeries(filepath, "s") + +times = u_timeseries.times + +@info "Make a movie of the splash..." + +using GLMakie + +n = Observable(1) + +title = @lift @sprintf("t = %s", prettytime(times[$n])) + +ζₙ = @lift interior(ζ_timeseries[$n], :, :, 1) +uₙ = @lift interior(u_timeseries[$n], :, :, 1) +vₙ = @lift interior(v_timeseries[$n], :, :, 1) +sₙ = @lift interior(s_timeseries[$n], :, :, 1) + +s_lim = maximum(abs, interior(s_timeseries)) +ζ₀ = maximum(abs, ζ_timeseries[end]) / 2 + +fig = Figure(size=(1200, 800)) + +ax_u = Axis(fig[1, 1], aspect=1) +ax_v = Axis(fig[1, 3], aspect=1) +ax_ζ = Axis(fig[2, 1], aspect=1) +ax_s = Axis(fig[2, 3], aspect=1) + +hm_u = heatmap!(ax_u, uₙ; colormap = :balance, colorrange = (-s_lim, s_lim)) +Colorbar(fig[1, 2], hm_u; label = "u (m s⁻¹)") + +hm_v = heatmap!(ax_v, vₙ; colormap = :balance, colorrange = (-s_lim, s_lim)) +Colorbar(fig[1, 4], hm_v; label = "v (m s⁻¹)") + +hm_ζ = heatmap!(ax_ζ, ζₙ; colormap = :balance, colorrange = (-ζ₀, ζ₀)) +Colorbar(fig[2, 2], hm_ζ; label = "ζ") + +hm_s = heatmap!(ax_s, sₙ; colormap = :speed, colorrange = (0, s_lim)) +Colorbar(fig[2, 4], hm_s; label = "√u²+v² (m s⁻¹)") + +fig[0, :] = Label(fig, title, tellwidth=false) + +fig + +frames = 1:length(times) + +record(fig, "polar_turbulence.mp4", frames, framerate = 12) do i + n[] = i +end + diff --git a/validation/orthogonal_spherical_shell_grid/rotated_lat_lon_splash.jl b/validation/orthogonal_spherical_shell_grid/rotated_lat_lon_splash.jl new file mode 100644 index 0000000000..d87adc2eb6 --- /dev/null +++ b/validation/orthogonal_spherical_shell_grid/rotated_lat_lon_splash.jl @@ -0,0 +1,132 @@ +using Oceananigans +using Oceananigans.Grids: RightConnected +using Oceananigans.OrthogonalSphericalShellGrids: RotatedLatitudeLongitudeGrid +using Oceananigans.OrthogonalSphericalShellGrids: rotate_coordinates +using Oceananigans.Units +using OrthogonalSphericalShellGrids: TripolarGrid +using Printf +using GLMakie +using Random + +size = (64, 64, 2) +latitude = (-60, 60) +longitude = (-60, 60) +z = (-1000, 0) +topology = (Bounded, Bounded, Bounded) + +η₀ = 1 +Δ = 10 +ηᵢ(λ, φ, z) = η₀ * exp(-(λ^2 + φ^2) / 2Δ^2) + +g1 = LatitudeLongitudeGrid(; size, latitude, longitude, z, topology) +g2 = RotatedLatitudeLongitudeGrid(; size, latitude, longitude, z, topology, north_pole=(0, 0)) + +momentum_advection = VectorInvariant() +closure = ScalarDiffusivity(ν=2e-4, κ=2e-4) +m1 = HydrostaticFreeSurfaceModel(grid=g1; closure, momentum_advection) +m2 = HydrostaticFreeSurfaceModel(grid=g2; closure, momentum_advection) + +Random.seed!(123) +ϵᵢ(λ, φ, z) = 1e-6 * randn() +set!(m1, η=ηᵢ, u=ϵᵢ, v=ϵᵢ) + +set!(m2, η = interior(m1.free_surface.η), + u = interior(m1.velocities.u), + v = interior(m1.velocities.v)) + +models = (unrotated=m1, rotated=m2) + +for name in keys(models) + model = models[name] + Δt = 3minutes + simulation = Simulation(model, Δt=Δt, stop_time=2days) + + progress_message(sim) = @printf("Iteration: %04d, time: %s, Δt: %s, wall time: %s\n", + iteration(sim), prettytime(sim), prettytime(sim.Δt), + prettytime(sim.run_wall_time)) + + simulation.callbacks[:progress] = Callback(progress_message, IterationInterval(100)) + + u, v, w = model.velocities + η = model.free_surface.η + s = @at (Center, Center, Center) sqrt(u^2 + v^2) + + simulation.output_writers[:splash] = JLD2OutputWriter(model, (; u, v, s, η), + schedule = IterationInterval(6), + filename = "splash_$name", + overwrite_existing = true) + + @info "Run simulation..." + run!(simulation) +end + +@show interior(m1.free_surface.η) == interior(m2.free_surface.η) +@show interior(m1.velocities.u) == interior(m2.velocities.u) +@show interior(m1.velocities.v) == interior(m2.velocities.v) + +filepath1 = "splash_unrotated" +filepath2 = "splash_rotated" + +η1 = FieldTimeSeries(filepath1, "η") +u1 = FieldTimeSeries(filepath1, "u") +v1 = FieldTimeSeries(filepath1, "v") +s1 = FieldTimeSeries(filepath1, "s") + +η2 = FieldTimeSeries(filepath2, "η") +u2 = FieldTimeSeries(filepath2, "u") +v2 = FieldTimeSeries(filepath2, "v") +s2 = FieldTimeSeries(filepath2, "s") + +n = Observable(1) + +η1n = @lift interior(η1[$n], :, :, 1) +u1n = @lift interior(u1[$n], :, :, 1) +v1n = @lift interior(v1[$n], :, :, 1) +s1n = @lift interior(s1[$n], :, :, 1) + +η2n = @lift interior(η2[$n], :, :, 1) +u2n = @lift interior(u2[$n], :, :, 1) +v2n = @lift interior(v2[$n], :, :, 1) +s2n = @lift interior(s2[$n], :, :, 1) + +fig = Figure(size=(1400, 800)) + +ax1 = Axis(fig[2, 1]) +ax2 = Axis(fig[2, 2]) +ax3 = Axis(fig[2, 3]) +ax4 = Axis(fig[2, 4]) + +ax5 = Axis(fig[3, 1]) +ax6 = Axis(fig[3, 2]) +ax7 = Axis(fig[3, 3]) +ax8 = Axis(fig[3, 4]) + +hm = heatmap!(ax1, η1n) +Colorbar(fig[1, 1], hm; label = "η (m)", vertical=false) + +hm = heatmap!(ax2, u1n) +Colorbar(fig[1, 2], hm; label = "u (m s⁻¹)", vertical=false) + +hm = heatmap!(ax3, v1n) +Colorbar(fig[1, 3], hm; label = "v (m s⁻¹)", vertical=false) + +hm = heatmap!(ax4, s1n) +Colorbar(fig[1, 4], hm; label = "√(u² + v²) (m s⁻¹)", vertical=false) + +heatmap!(ax5, η2n) +heatmap!(ax6, u2n) +heatmap!(ax7, v2n) +heatmap!(ax8, s2n) + +times = u1.times +title = @lift @sprintf("t = %s", prettytime(times[$n])) +Label(fig[0, 1:4], title, tellwidth=false) + +display(fig) + +frames = 1:length(times) + +record(fig, "splash.mp4", frames, framerate = 12) do nn + n[] = nn +end +