Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

GeoMakie extension and interactive 3D grid visualisation on the sphere #600

Merged
merged 33 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
37f0f9f
make Geometry parametric with Grid
milankl Oct 29, 2024
1ba97ac
GeoMakie extension, globe for interactive 3D visualisation
milankl Oct 29, 2024
fa44b6a
add Geodesy as weak dependency too
milankl Oct 29, 2024
81742f2
ext deps as markdown list
milankl Oct 29, 2024
256f059
function args typo
milankl Oct 29, 2024
1402467
export globe
milankl Oct 29, 2024
584d460
changelog updated
milankl Oct 29, 2024
45d8c70
update docs toml
milankl Oct 29, 2024
f5a1642
remove Geodesy dependency
milankl Oct 29, 2024
dc7908e
move ext into folder
milankl Oct 29, 2024
cf1e561
_faces typo
milankl Oct 29, 2024
5dd7397
add OctahedralGaussian method for _faces
milankl Oct 29, 2024
a505166
remove equator for even rings
milankl Oct 29, 2024
f9a2106
include octahedral clenshaw grids
milankl Oct 29, 2024
5d0a325
faces, facesr not returned
milankl Oct 29, 2024
6cece11
Merge branch 'main' into mk/globe
milankl Nov 5, 2024
23c4061
get_vertices for RingGrids
milankl Nov 8, 2024
c87e1d2
Merge branch 'mk/globe' of https://github.com/SpeedyWeather/SpeedyWea…
milankl Nov 8, 2024
0bc27ba
globe options
milankl Nov 8, 2024
5809b59
vertices for full grids just rectangles, not diamonds
milankl Nov 8, 2024
374ccec
globe for data
milankl Nov 9, 2024
25aa116
extend not overwrite globe
milankl Nov 9, 2024
1d6fe0d
import Polygon and docstrings
milankl Nov 10, 2024
5f49630
import Polygon through GeoMakie
milankl Nov 10, 2024
c992c96
interactive bool
milankl Nov 11, 2024
d0d602c
title corrected
milankl Nov 11, 2024
97a31ff
change vertices definiton to ESWN
milankl Nov 11, 2024
d7006b2
use globe function in docs
milankl Nov 11, 2024
8366525
Update Project.toml
milankl Nov 11, 2024
e32240a
more globe calls in docs
milankl Nov 11, 2024
e35b02b
docs typo
milankl Nov 11, 2024
68ebd01
Merge branch 'mk/globe' of https://github.com/SpeedyWeather/SpeedyWea…
milankl Nov 11, 2024
a709b59
Update ext/SpeedyWeatherGeoMakieExt/faces.jl
milankl Nov 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- GeoMakie weak dependecy, globe function for 3D data visualisation [#600](https://github.com/SpeedyWeather/SpeedyWeather.jl/pull/600)

## v0.12.0

- OctaminimalGaussianArray/Grid to start with 4 points around the poles [#595](https://github.com/SpeedyWeather/SpeedyWeather.jl/pull/595)
Expand Down
3 changes: 3 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"

[weakdeps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
GeoMakie = "db073c08-6b98-4ee5-b6a4-5efafb3259c6"
JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb"
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"

[extensions]
SpeedyWeatherCUDAExt = "CUDA"
SpeedyWeatherGeoMakieExt = "GeoMakie"
SpeedyWeatherJLArraysExt = "JLArrays"
SpeedyWeatherMakieExt = "Makie"

Expand All @@ -50,6 +52,7 @@ FFTW = "1"
FastGaussQuadrature = "0.4, 0.5, 1"
GPUArrays = "10"
GenericFFT = "0.1"
GeoMakie = "0.7.5"
milankl marked this conversation as resolved.
Show resolved Hide resolved
JLArrays = "0.1.4"
JLD2 = "0.4, 0.5"
KernelAbstractions = "0.9"
Expand Down
6 changes: 3 additions & 3 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ NCDatasets = "85f8d34a-cbdd-5861-8df4-14fed0d494ab"
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"

[compat]
CairoMakie = "0.11"
CairoMakie = "0.11, 0.12"
Documenter = "0.26, 0.27, 1"
GeoMakie = "0.6"
GeoMakie = "0.7.5"
NCDatasets = "0.12, 0.13, 0.14"
UnicodePlots = "3.3"
UnicodePlots = "3"
59 changes: 59 additions & 0 deletions ext/SpeedyWeatherGeoMakieExt/SpeedyWeatherGeoMakieExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module SpeedyWeatherGeoMakieExt

using SpeedyWeather
using GeoMakie

include("faces.jl")

SpeedyWeather.globe(Grid::Type{<:AbstractGridArray}, nlat_half::Integer) = SpeedyWeather.globe(SpectralGrid(; Grid, nlat_half))
SpeedyWeather.globe(SG::SpectralGrid) = globe(Geometry(SG))

function SpeedyWeather.globe(geometry::Geometry{NF, Grid}) where {NF, Grid}

faces, facesr = _faces(geometry)

transf = GeoMakie.Geodesy.ECEFfromLLA(GeoMakie.Geodesy.WGS84())

fig = Figure(size=(800, 800));
ax = LScene(fig[1,1], show_axis=false);

# background image
bg = meshimage!(ax, -180..180, -90..90, rotr90(GeoMakie.earth()); npoints = 100, z_level = -10_000);
bg.transformation.transform_func[] = transf

# cell centers
color = :black
s = scatter!(ax, geometry.londs, geometry.latds, markersize=5; color)
s.transformation.transform_func[] = transf

# cell faces
for i in 1:geometry.nlon_max÷4
for offset in [0, 90, 180, 270]
lp1 = lines!(ax, facesr[i, :, 1] .+ offset, facesr[i, :, 2]; color)
lp2 = lines!(ax, offset .- faces[i, :, 1], faces[i, :, 2]; color)

lp1.transformation.transform_func[] = transf
lp2.transformation.transform_func[] = transf
end
end
milankl marked this conversation as resolved.
Show resolved Hide resolved

if RingGrids.nlat_odd(Grid) == false
# add equator
lpe = lines!(ax, 0:360, zeros(361); color)
lpe.transformation.transform_func[] = transf
end

# coastlines
lpc = lines!(GeoMakie.coastlines(50); color, linewidth=1)
lpc.transformation.transform_func[] = transf

# Makie stuff
cc = cameracontrols(ax.scene)
cc.settings.mouse_translationspeed[] = 0.0
cc.settings.zoom_shift_lookat[] = false
Makie.update_cam!(ax.scene, cc)

return fig
end

end # module
65 changes: 65 additions & 0 deletions ext/SpeedyWeatherGeoMakieExt/faces.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
function _faces(geometry::Geometry{NF, Grid}) where {NF, Grid<:OctaminimalGaussianArray}

faces = zeros(geometry.nlon_max÷4+1, geometry.nlat+2, 2)
fill!(faces, NaN)
facesr = deepcopy(faces)

for (j, latd) in enumerate(geometry.latd)
nlon = RingGrids.get_nlon_per_ring(Grid, geometry.nlat_half, j)
lond = RingGrids.get_lon_per_ring(Grid, geometry.nlat_half, j) * (360/2π)
nlon ÷= 4
dϕ = 90/nlon

for i in 1:nlon
faces[i, j+1, 1] = lond[i] + dϕ/2
faces[i, j+1, 2] = latd
facesr[i, j+1, :] = faces[i, j+1, :]
end

facesr[nlon+1, 1, :] .= NaN # remove to avoid overlapping grid lines at edges

faces[end-1, j+1, 1] = 90
faces[end-1, j+1, 2] = latd
end

# continue to the poles
faces[:, 1, 1] = faces[:, 2, 1]
faces[:, 1, 2] .= 90

faces[:, end, 1] = faces[:, end-1, 1]
faces[:, end, 2] .= -90

return faces, facesr
end

function _faces(geometry::Geometry{NF, Grid}) where {NF, Grid<:Union{OctahedralGaussianArray, OctahedralClenshawArray}}

faces = zeros(geometry.nlon_max÷4+1, geometry.nlat+2, 2)
fill!(faces, NaN)
facesr = deepcopy(faces)

for (j, latd) in enumerate(geometry.latd)
nlon = RingGrids.get_nlon_per_ring(Grid, geometry.nlat_half, j)
lond = RingGrids.get_lon_per_ring(Grid, geometry.nlat_half, j) * (360/2π)
nlon ÷= 4
dϕ = 90/nlon

for i in 1:nlon+1
faces[i, j+1, 1] = lond[i] + dϕ/2
faces[i, j+1, 2] = latd
facesr[i, j+1, :] = faces[i, j+1, :]
end

facesr[nlon+1, 1, :] .= NaN # remove to avoid overlapping grid lines at edges
facesr[nlon+1, j+1, :] .= NaN # remove to avoid overlapping grid lines at edges
end

# continue to the poles
faces[:, 1, 1] = faces[:, 2, 1]
faces[:, 1, 2] .= 90

faces[:, end, 1] = faces[:, end-1, 1]
faces[:, end, 2] .= -90

return faces, facesr
end
4 changes: 4 additions & 0 deletions src/SpeedyWeather.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ include("SpeedyTransforms/SpeedyTransforms.jl")
using .SpeedyTransforms
import .SpeedyTransforms: prettymemory

# to be defined in GeoMakie extension
export globe
function globe end

# Utility for GPU / KernelAbstractions
include("gpu.jl")

Expand Down
17 changes: 7 additions & 10 deletions src/dynamics/geometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ Construct Geometry struct containing parameters and arrays describing an iso-lat
and the vertical levels. Pass on `SpectralGrid` to calculate the following fields
$(TYPEDFIELDS)
"""
@kwdef struct Geometry{NF<:AbstractFloat} <: AbstractGeometry
@kwdef struct Geometry{NF<:AbstractFloat, Grid<:AbstractGrid} <: AbstractGeometry

"SpectralGrid that defines spectral and grid resolution"
spectral_grid::SpectralGrid

"grid of the dynamical core"
Grid::Type{<:AbstractGrid} = spectral_grid.Grid

"resolution parameter nlat_half of Grid, # of latitudes on one hemisphere (incl Equator)"
nlat_half::Int = spectral_grid.nlat_half

Expand All @@ -32,7 +29,7 @@ $(TYPEDFIELDS)
"number of vertical levels"
nlayers::Int = spectral_grid.nlayers

"total number of grid points"
"total number of horizontal grid points"
npoints::Int = spectral_grid.npoints

"Planet's radius [m]"
Expand Down Expand Up @@ -99,11 +96,11 @@ end
"""
$(TYPEDSIGNATURES)
Generator function for `Geometry` struct based on `spectral_grid`."""
function Geometry(spectral_grid::SpectralGrid)
error_message = "nlayers=$(spectral_grid.nlayers) does not match length nlayers="*
"$(spectral_grid.vertical_coordinates.nlayers) in spectral_grid.vertical_coordinates."
@assert spectral_grid.nlayers == spectral_grid.vertical_coordinates.nlayers error_message
return Geometry{spectral_grid.NF}(; spectral_grid)
function Geometry(SG::SpectralGrid)
error_message = "nlayers=$(SG.nlayers) does not match length nlayers="*
"$(SG.vertical_coordinates.nlayers) in spectral_grid.vertical_coordinates."
@assert SG.nlayers == SG.vertical_coordinates.nlayers error_message
return Geometry{SG.NF, SG.Grid}(; spectral_grid=SG)
end

function Base.show(io::IO, G::Geometry)
Expand Down
4 changes: 2 additions & 2 deletions src/dynamics/prognostic_variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,8 @@ function set!(var::LowerTriangularArray, grids::AbstractGridArray, geometry::Uni
end

# set LTA <- func
function set!(var::LowerTriangularArray, f::Function, geometry::Geometry{NF}, S::Union{SpectralTransform, Nothing}=nothing; add::Bool) where NF
grid = ndims(var) == 1 ? zeros(geometry.Grid{NF}, geometry.nlat_half) : zeros(geometry.Grid{NF}, geometry.nlat_half, geometry.nlayers)
function set!(var::LowerTriangularArray, f::Function, geometry::Geometry{NF, Grid}, S::Union{SpectralTransform, Nothing}=nothing; add::Bool) where {NF, Grid}
grid = ndims(var) == 1 ? zeros(Grid{NF}, geometry.nlat_half) : zeros(Grid{NF}, geometry.nlat_half, geometry.nlayers)
set!(grid, f, geometry, S; add=false)
set!(var, grid, geometry, S; add)
end
Expand Down
8 changes: 3 additions & 5 deletions src/physics/tendencies.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ function parameterization_tendencies!(
# TODO move into shortwave radiation code?
cos_zenith!(diagn, time, model)

G = model.geometry
rings = eachring(G.Grid, G.nlat_half)

for ij in eachgridpoint(diagn) # loop over all horizontal grid points
rings = eachring(diagn.grid.vor_grid) # indices on every latitude ring
for ij in eachgridpoint(diagn) # loop over all horizontal grid points

thread_id = Threads.threadid() # not two threads should use the same ColumnVariables
column = diagn.columns[thread_id]
jring = whichring(ij, rings) # ring index gridpoint ij is on
jring = whichring(ij, rings) # ring index gridpoint ij is on

# extract current column for contiguous memory access
reset_column!(column) # set accumulators back to zero for next grid point
Expand Down
1 change: 0 additions & 1 deletion test/spectral_gradients.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ end
HEALPixGrid)

SG = SpectralGrid(; NF, Grid, nlayers=1)
G = Geometry(SG)

A = Grid(randn(NF, SG.npoints))
B = copy(A)
Expand Down