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

Restructured dynamical core, variables array-agnostic and 3-dimensional, modular netCDF output #525

Merged
merged 120 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from 112 commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
322afb3
PrognosticVariables with LowerTriangularArray
milankl Apr 25, 2024
6ad2472
WIP: initial indexing changes
maximilian-gelbrecht May 16, 2024
d48246b
WIP: indexing not working yet
maximilian-gelbrecht May 17, 2024
624654a
WIP indexing (probably) working
maximilian-gelbrecht May 17, 2024
94a8337
WIP: zeros, ones, rand, ...
maximilian-gelbrecht May 17, 2024
37045fc
WIP: copyto!
maximilian-gelbrecht May 17, 2024
3249876
copyto! working
maximilian-gelbrecht May 18, 2024
2997c3e
LTA N-1 dim change tests passing
maximilian-gelbrecht May 18, 2024
4873de7
adjusting for size(alms)
maximilian-gelbrecht May 21, 2024
eb8725b
fast cartesian indexing + broadcasting
maximilian-gelbrecht May 22, 2024
a7183f9
clean up explicit arithmetics functions
maximilian-gelbrecht May 22, 2024
bc196fe
code cleanup broadcasting
maximilian-gelbrecht May 22, 2024
df15546
remove add! tests
maximilian-gelbrecht May 22, 2024
676c630
show LowerTriangularMatrix
milankl May 22, 2024
6fea1c5
fix LTA plot
maximilian-gelbrecht May 23, 2024
b884c56
PrognosticVariables new structure
milankl May 23, 2024
90100cb
DiagnosticVariables new structure
milankl May 23, 2024
8ab67c1
zeros for Vector{Particle}
milankl May 23, 2024
891987e
no set vars tests due to new structure
milankl May 23, 2024
ccdc992
SpectralGrid with Spectral/GridVariable2D/3D types
milankl May 23, 2024
0ff4f5f
progn/diagn prettier printing
milankl May 23, 2024
40358d3
fill!(::Tendencies, x) instead of zero_tendencies!
milankl May 24, 2024
8730dc8
prognostic variables as NTuple{2, LowerTriangularArray}
milankl May 24, 2024
ee42b31
BarotropicModel without layer structure
milankl May 24, 2024
e1cbf24
N-dimensional transform! spec->grid
milankl May 24, 2024
bfeb2db
Merge branch 'main' into mk/newvariables
milankl May 24, 2024
ac6af8b
n-dim transform! also grid -> spectral
milankl May 24, 2024
26ca59a
CartesianIndex{0} and broadcast tests
maximilian-gelbrecht May 30, 2024
e4dd023
LTA tests fixed
maximilian-gelbrecht May 30, 2024
ad6f527
SpectralTransform adjusted to ndim-1 LTA, still WIP
maximilian-gelbrecht May 30, 2024
b33fedb
Merge branch 'main' into mg/lta-ndim-1
maximilian-gelbrecht May 30, 2024
d146f36
n-dim leapfrogging
milankl May 30, 2024
575f72a
Merge branch 'mg/lta-ndim-1' into mk/newvariables
milankl May 30, 2024
8be0d59
n-dimensional UV_from_vor!
milankl May 30, 2024
d7075d2
BarotropicModel with n-dim formulation
milankl May 30, 2024
24b6339
define prognostic_variables(::ModelSetup)
milankl Jun 4, 2024
59c2c81
shallow water model with new array structure
milankl Jun 4, 2024
c181fc1
First working shallow water model with new variable structure
milankl Jun 4, 2024
b8737f7
Spectral gradients with better size checks
milankl Jun 5, 2024
88c7e2b
horizontal diffusion with nlayers
milankl Jun 10, 2024
d9e070a
implicit, land, ocean adapted to new structure
milankl Jun 10, 2024
9505328
First half of the primitive equation dynamical core restructured
milankl Jun 12, 2024
8829129
surface pressure tendency, vertical velocity and linear pres gradient…
milankl Jun 13, 2024
4d3de41
vertical advection to new structure
milankl Jun 21, 2024
bb2d710
vor, div, temp, humid tendencies, implicit and diffusion
milankl Jun 23, 2024
c88a4f2
physics_tendencies_only! renaming
milankl Jun 26, 2024
2b34e92
Merge branch 'main' into mk/newvariables
milankl Jul 5, 2024
e333f67
Further size calls for LTA corrected
milankl Jul 5, 2024
c9181d9
replace spectral/gridded functions with transform
milankl Jul 6, 2024
9627a5e
transform and gradient tests passing
milankl Jul 7, 2024
eaa96e8
Merge branch 'main' into mk/newvariables
milankl Jul 7, 2024
f9e3d06
more tests adapted
milankl Jul 8, 2024
45e378e
Merge branch 'mk/newvariables' of https://github.com/SpeedyWeather/Sp…
milankl Jul 8, 2024
1f9139e
extending tests adapted
milankl Jul 8, 2024
fabaf4f
Merge branch 'main' into mk/newvariables
milankl Jul 9, 2024
8feb0e6
Merge branch 'main' into mk/newvariables
milankl Jul 9, 2024
4210d99
nlayers instead of nlev; starting to adjust docs
maximilian-gelbrecht Jul 25, 2024
ee57a65
docs rework contiues
maximilian-gelbrecht Jul 25, 2024
f7bef4a
benchmark suite nlayers spectral grid call
maximilian-gelbrecht Jul 25, 2024
90ebfd3
further docs updated
maximilian-gelbrecht Jul 26, 2024
5e5a31f
doc add section about batched transforms
maximilian-gelbrecht Jul 26, 2024
d921275
typo in docs
maximilian-gelbrecht Jul 26, 2024
f901e4d
docs: another typo
maximilian-gelbrecht Jul 26, 2024
957b4f1
changelog updated
milankl Jul 26, 2024
b86f765
Merge branch 'mg/newvariables' of https://github.com/SpeedyWeather/Sp…
milankl Jul 26, 2024
dbc5bd9
New 4D Variable Structure: nlayers instead of nlev; starting to adjus…
maximilian-gelbrecht Jul 26, 2024
645cc6f
Merge branch 'mk/newvariables' of https://github.com/SpeedyWeather/Sp…
milankl Jul 26, 2024
ddf3408
all merged
milankl Jul 26, 2024
53dcd5d
rename ModelSetup to AbstractModel
milankl Aug 1, 2024
6940135
NetCDF output modularised (#573)
milankl Aug 29, 2024
cfab463
Merge branch 'main' into mk/newvariables
milankl Aug 29, 2024
3940d55
particle tracker test adapted
milankl Aug 29, 2024
570d3fc
Merge branch 'mk/newvariables' of https://github.com/SpeedyWeather/Sp…
milankl Aug 29, 2024
c02773c
bugs in netcdf output tests
milankl Aug 29, 2024
b88cd9f
include previous bugfix changelog
milankl Aug 29, 2024
11ebf22
benchmarks nlayer/nlev fixed
maximilian-gelbrecht Aug 29, 2024
4569ec2
Merge branch 'main' into mk/newvariables
milankl Sep 5, 2024
4c5d72a
add @inbounds back in
milankl Sep 11, 2024
a1c0692
Merge branch 'main' into mk/newvariables
milankl Sep 11, 2024
7d63723
constrain to julia 1.10
milankl Sep 11, 2024
463b11f
Merge branch 'mk/newvariables' of https://github.com/SpeedyWeather/Sp…
milankl Sep 11, 2024
a9b8c14
CI with prelease for 1.11
milankl Sep 11, 2024
23726d8
add dependabot.yml
milankl Sep 11, 2024
2edfab0
update CI.yml
milankl Sep 11, 2024
391398b
move dependabot
milankl Sep 11, 2024
b7c7bf1
Tuple instead of vector of different grids, latter fails in 1.9
milankl Sep 11, 2024
cbad58b
CI with 1.9 again
milankl Sep 11, 2024
f8f1bd1
grid creation with Grid(grid.data) to avoid double nesting
milankl Sep 11, 2024
2b67b22
define JLArray method for julia v1.9
milankl Sep 12, 2024
d22bef5
set compat to Julia 1.9 again
milankl Sep 12, 2024
08315c1
JetStreamForcing adapted
milankl Sep 12, 2024
2f46d95
bug: wrote restart even without output
milankl Sep 12, 2024
14d065a
output show with restart information
milankl Sep 12, 2024
fd168e9
RandomWaves initial conditions adapted
milankl Sep 13, 2024
8c2e438
docs: extensions/forcing_drag adapted
milankl Sep 13, 2024
daf6645
transforms with singleton dimensions possible
milankl Sep 13, 2024
f0d3678
test real to real transform
milankl Sep 13, 2024
6da0f2d
Transfroms: More number format flexibility tests
milankl Sep 16, 2024
8427403
docs build errors addressed
milankl Sep 16, 2024
7d9b700
first version NetCDFOutput new documentation
milankl Sep 16, 2024
461f5bf
docs: particle advection with 2D shallow water model nlayers=1
milankl Sep 17, 2024
3fc17be
make nlayers>1 warn an error for 2D models
milankl Sep 17, 2024
7b246e9
Improved error message for `ismatching`
milankl Sep 17, 2024
cbcedba
docs speedytransforms
milankl Sep 17, 2024
dbaae74
docs: add variables to netcdf
milankl Sep 17, 2024
eb9309a
docs misc
milankl Sep 17, 2024
b048e37
docs: extending netCDF output
milankl Sep 18, 2024
546db6f
custom netcdf output
milankl Sep 18, 2024
baa3a84
docs: custom netcdf output finished
milankl Sep 18, 2024
b191e6b
Set! function for PrognosticVariables and ICs for new structure (#563)
maximilian-gelbrecht Sep 19, 2024
139ab28
export set!
milankl Sep 19, 2024
91e76df
reworking UV from vordiv tests with set!
milankl Sep 19, 2024
c3f7398
move radius keyword into spectral gradient kernels
milankl Sep 20, 2024
87c846a
set! linting
milankl Sep 20, 2024
b61bd7c
spectral gradients: typo corrected
milankl Sep 23, 2024
4fc9414
@inbounds in dynamics tendencies
milankl Sep 24, 2024
4088358
FLoops dependency removed
milankl Sep 24, 2024
5a3e4e2
allocation free vertical velocity
milankl Sep 24, 2024
1ce6fdb
(almost) non-allocating vertical advection
milankl Sep 24, 2024
ca4ea51
general vertical advection stencil via ntuple
milankl Sep 25, 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: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ updates:
- package-ecosystem: "github-actions"
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
interval: "weekly"
12 changes: 2 additions & 10 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
version:
- '1.9'
- '1.10'
- '~1.11.0-0'
os:
- ubuntu-latest
arch:
Expand All @@ -25,16 +26,7 @@ jobs:
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: actions/cache@v4
env:
cache-name: cache-artifacts
with:
path: ~/.julia/artifacts
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
restore-keys: |
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
env:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ default.profraw

# vs code
.vscode
settings.json
settings.json
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

## Unreleased

- Introduced a new `set!` function that allows to set `PrognosticVariables` to new values with keyword arguments
- Restructured dynamical core with prognostic/diagnostic variables array-agnostic and 3-dimensional [#525](https://github.com/SpeedyWeather/SpeedyWeather.jl/pull/525)
- Modularised NetCDF output [#573](https://github.com/SpeedyWeather/SpeedyWeather.jl/pull/573)
- Fixed a bug in RingGrids, now broadcasts are defined even when the dimensions mismatch in some cases [#568](https://github.com/SpeedyWeather/SpeedyWeather.jl/pull/568)
- RingGrids: To wrap an Array with the horizontal dimension in matrix shape into a full grid, one has to use e.g. `FullGaussianGrid(map, input_as=Matrix)` now. [#572](https://github.com/SpeedyWeather/SpeedyWeather.jl/pull/572)
* RingGrids: Fixed a bug in `RingGrids`, so that now broadcasts are defined even when the dimensions mismatch in some cases
* CompatHelper: Allow for JLD2.jl v0.5
- CompatHelper: Allow for JLD2.jl v0.5

## v0.11.0
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The interface to SpeedyWeather.jl consist of 5 steps: define the grid, create mo
construct the model, initialize, run

```julia
spectral_grid = SpectralGrid(trunc=31, nlev=8) # define resolution
spectral_grid = SpectralGrid(trunc=31, nlayers=8) # define resolution
orography = EarthOrography(spectral_grid) # create non-default components
model = PrimitiveWetModel(; spectral_grid, orography) # construct model
simulation = initialize!(model) # initialize all model components
Expand Down
6 changes: 3 additions & 3 deletions benchmark/benchmark_suite.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ function run_benchmark_suite!(suite::BenchmarkSuite)
Model = suite.model[i]
NF = suite.NF[i]
trunc = suite.trunc[i]
nlev = suite.nlev[i]
nlayers = suite.nlev[i]
Grid = suite.Grid[i]
dynamics = suite.dynamics[i]
physics = suite.physics[i]

spectral_grid = SpectralGrid(;NF, trunc, Grid, nlev)
spectral_grid = SpectralGrid(;NF, trunc, Grid, nlayers)
suite.nlat[i] = spectral_grid.nlat

model = Model(;spectral_grid)
Expand All @@ -50,7 +50,7 @@ function run_benchmark_suite!(suite::BenchmarkSuite)
simulation = initialize!(model)
suite.memory[i] = Base.summarysize(simulation)

nsteps = n_timesteps(trunc, nlev)
nsteps = n_timesteps(trunc, nlayers)
period = Second(round(Int,model.time_stepping.Δt_sec * (nsteps+1)))
run!(simulation; period)

Expand Down
2 changes: 1 addition & 1 deletion benchmark/manual_benchmarking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ write(md, "### Explanation\n\n")
write(md, "Abbreviations in the tables below are as follows, omitted columns use defaults.\n")
write(md, "- NF: Number format, default: $(SpeedyWeather.DEFAULT_NF)\n")
write(md, "- T: Spectral resolution, maximum degree of spherical harmonics, default: T$(SpeedyWeather.DEFAULT_TRUNC)\n")
write(md, "- L: Number of vertical layers, default: $(SpeedyWeather.DEFAULT_NLEV) (for 3D models)\n")
write(md, "- L: Number of vertical layers, default: $(SpeedyWeather.DEFAULT_NLAYERS) (for 3D models)\n")
write(md, "- Grid: Horizontal grid, default: $(SpeedyWeather.DEFAULT_GRID)\n")
write(md, "- Rings: Grid-point resolution, number of latitude rings pole to pole\n")
write(md, "- Dynamics: With dynamics?, default: true\n")
Expand Down
4 changes: 3 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Documenter, SpeedyWeather
using Documenter
using SpeedyWeather

makedocs(
format = Documenter.HTML(prettyurls=get(ENV, "CI", nothing)=="true",
Expand All @@ -25,6 +26,7 @@ makedocs(
"Orography"=>"orography.md",
"Land-Sea Mask"=>"land_sea_mask.md",
"Ocean"=>"ocean.md",
"NetCDF output variables"=>"custom_netcdf_output.md",
"Callbacks"=>"callbacks.md",
],
"Dynamics" => [
Expand Down
81 changes: 46 additions & 35 deletions docs/src/analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ or wavenumber 0, see [Spherical Harmonic Transform](@ref)) encodes the global av

```@example analysis
using SpeedyWeather
spectral_grid = SpectralGrid(trunc=31, nlev=1)
spectral_grid = SpectralGrid(trunc=31, nlayers=1)
model = ShallowWaterModel(;spectral_grid)
simulation = initialize!(model)
```
Expand All @@ -77,19 +77,19 @@ Now we check ``\eta_{0,0}`` the ``l = m = 0`` coefficent of the inital condition
of that simulation with

```@example analysis
simulation.prognostic_variables.surface.timesteps[1].pres[1]
simulation.prognostic_variables.pres[1][1]
```

`[1]` pulls the first element of the underlying [LowerTriangularMatrix](@ref lowertriangularmatrices)
which is the coefficient of the ``l = m = 0`` mode.
Its imaginary part is always zero (which is true for any zonal harmonic ``m=0`` as its
`[1][1]` pulls the first Leapfrog time step and of that the first element of the underlying
[LowerTriangularMatrix](@ref lowertriangularmatrices) which is the coefficient of the ``l = m = 0``
harmonic. Its imaginary part is always zero (which is true for any zonal harmonic ``m=0`` as its
imaginary part would just unnecessarily rotate something zonally constant in zonal direction),
so you can `real` it. Also for spherical harmonic transforms there is a norm of the sphere
by which you have to divide to get your mean value in the original units

```@example analysis
a = model.spectral_transform.norm_sphere # = 2√π = 3.5449078
η_mean = real(simulation.prognostic_variables.surface.timesteps[1].pres[1]) / a
η_mean = real(simulation.prognostic_variables.pres[1][1]) / a
```

So the initial conditions in this simulation are such that the global mean interface displacement
Expand All @@ -105,7 +105,7 @@ model.feedback.verbose = false # hide
run!(simulation, period=Day(10))

# now we check η_mean again
η_mean_later = real(simulation.prognostic_variables.surface.timesteps[1].pres[1]) / a
η_mean_later = real(simulation.prognostic_variables.pres[1][1]) / a
```

which is _exactly_ the same. So mass is conserved, woohoo.
Expand Down Expand Up @@ -146,7 +146,7 @@ function total_energy(u, v, η, model)
E = @. h/2*(u^2 + v^2) + g*h^2 # vertically-integrated mechanical energy

# transform to spectral, take l=m=0 mode at [1] and normalize for mean
return E_mean = real(spectral(E)[1]) / model.spectral_transform.norm_sphere
return E_mean = real(transform(E)[1]) / model.spectral_transform.norm_sphere
end
```

Expand All @@ -155,9 +155,9 @@ So at the current state of our simulation we have a total energy

```@example analysis
# flat copies for convenience
u = simulation.diagnostic_variables.layers[1].grid_variables.u_grid
v = simulation.diagnostic_variables.layers[1].grid_variables.v_grid
η = simulation.diagnostic_variables.surface.pres_grid
u = simulation.diagnostic_variables.grid.u_grid[:, 1]
v = simulation.diagnostic_variables.grid.v_grid[:, 1]
η = simulation.diagnostic_variables.grid.pres_grid

TE = total_energy(u, v, η, model)
```
Expand Down Expand Up @@ -209,11 +209,11 @@ as

```@example analysis
# vorticity
ζ = simulation.diagnostic_variables.layers[1].grid_variables.vor_grid
ζ = simulation.diagnostic_variables.grid.vor_grid[:,1]
f = coriolis(ζ) # create f on that grid

# layer thickness
η = simulation.diagnostic_variables.surface.pres_grid
η = simulation.diagnostic_variables.grid.pres_grid
H = model.atmosphere.layer_thickness
Hb = model.orography.orography
h = @. η + H - Hb
Expand All @@ -225,12 +225,21 @@ nothing # hide

and we can compare the relative vorticity field to
```@example analysis
plot(ζ)
using CairoMakie
heatmap(ζ, title="Relative vorticity [1/s]")
save("analysis_vor.png", ans) # hide
nothing # hide
```
![Relative vorticity](analysis_vor.png)


the potential vorticity
```@example analysis
plot(q)
heatmap(ζ, title="Potential vorticity [1/ms]")
save("analysis_pv.png", ans) # hide
nothing # hide
```
![Potential vorticity](analysis_pv.png)

## Absolute angular momentum

Expand Down Expand Up @@ -262,7 +271,7 @@ function total_angular_momentum(u, η, model)
Λ = @. (u*r + Ω*r^2) * h # vertically-integrated AAM

# transform to spectral, take l=m=0 mode at [1] and normalize for mean
return Λ_mean = real(spectral(Λ)[1]) / model.spectral_transform.norm_sphere
return Λ_mean = real(transform(Λ)[1]) / model.spectral_transform.norm_sphere
end
```

Expand Down Expand Up @@ -299,7 +308,7 @@ function total_circulation(ζ, model)
f = coriolis(ζ) # create f on the grid of ζ
C = ζ .+ f # absolute vorticity
# transform to spectral, take l=m=0 mode at [1] and normalize for mean
return C_mean = real(spectral(C)[1]) / model.spectral_transform.norm_sphere
return C_mean = real(transform(C)[1]) / model.spectral_transform.norm_sphere
end

total_circulation(ζ, model)
Expand Down Expand Up @@ -336,7 +345,7 @@ function total_enstrophy(ζ, η, model)
Q = @. q^2 / 2 # Potential enstrophy

# transform to spectral, take l=m=0 mode at [1] and normalize for mean
return Q_mean = real(spectral(Q)[1]) / model.spectral_transform.norm_sphere
return Q_mean = real(transform(Q)[1]) / model.spectral_transform.norm_sphere
end
```

Expand Down Expand Up @@ -373,14 +382,14 @@ to show how to global integral ``\iint dV`` can be written more efficiently
# define a global integral, reusing a precomputed SpectralTransform S
# times surface area of sphere omitted
function ∬dA(v, h, S::SpectralTransform)
return real(spectral(v .* h, S)[1]) / S.norm_sphere
return real(transform(v .* h, S)[1]) / S.norm_sphere
end

# use SpectralTransform from model
∬dA(v, h, model::ModelSetup) = ∬dA(v, h, model.spectral_transform)
∬dA(v, h, model::AbstractModel) = ∬dA(v, h, model.spectral_transform)
```
By reusing `model.spectral_transform` we do not have to re-precompute
the spectral tranform on every call to `spectral`. Providing
the spectral tranform on every call to `transform`. Providing
the spectral transform from model as the 2nd argument simply reuses
a previously precomputed spectral transform which is much faster
and uses less memory.
Expand All @@ -389,22 +398,24 @@ Now the `global_diagnostics` function is defined as

```@example analysis
function global_diagnostics(u, v, ζ, η, model)

# constants from model
NF = model.spectral_grid.NF # number format used
H = model.atmosphere.layer_thickness
Hb = model.orography.orography
R = model.spectral_grid.radius
Ω = model.planet.rotation
g = model.planet.gravity

r = R * cos.(model.geometry.lats) # create r on that grid
f = coriolis(u) # create f on that grid
r = NF.(R * cos.(model.geometry.lats)) # create r on that grid
f = coriolis(u) # create f on that grid

h = @. η + H - Hb # thickness
q = @. (ζ + f) / h # potential vorticity
λ = @. u * r + Ω * r^2 # angular momentum
k = @. 1/2 * (u^2 + v^2) # kinetic energy
p = @. 1/2 * g * h # potential energy
z = @. q^2/2 # potential enstrophy
λ = @. u * r + Ω * r^2 # angular momentum (in the right number format NF)
k = @. (u^2 + v^2) / 2 # kinetic energy
p = @. g * h / 2 # potential energy
z = @. q^2 / 2 # potential enstrophy

M = ∬dA(1, h, model) # mean mass
C = ∬dA(q, h, model) # mean circulation
Expand All @@ -417,11 +428,11 @@ function global_diagnostics(u, v, ζ, η, model)
end

# unpack diagnostic variables and call global_diagnostics from above
function global_diagnostics(diagn::DiagnosticVariables, model::ModelSetup)
u = diagn.layers[1].grid_variables.u_grid
v = diagn.layers[1].grid_variables.v_grid
ζR = diagn.layers[1].grid_variables.vor_grid
η = diagn.surface.pres_grid
function global_diagnostics(diagn::DiagnosticVariables, model::AbstractModel)
u = diagn.grid.u_grid[:, 1]
v = diagn.grid.v_grid[:, 1]
ζR = diagn.grid.vor_grid[:, 1]
η = diagn.grid.pres_grid

# vorticity during simulation is scaled by radius R, unscale here
ζ = ζR ./ diagn.scale[]
Expand Down Expand Up @@ -465,7 +476,7 @@ function SpeedyWeather.initialize!(
callback::GlobalDiagnostics,
progn::PrognosticVariables,
diagn::DiagnosticVariables,
model::ModelSetup,
model::AbstractModel,
)
# replace with vector of correct length
n = progn.clock.n_timesteps + 1 # +1 for initial conditions
Expand Down Expand Up @@ -497,7 +508,7 @@ function SpeedyWeather.callback!(
callback::GlobalDiagnostics,
progn::PrognosticVariables,
diagn::DiagnosticVariables,
model::ModelSetup,
model::AbstractModel,
)
callback.timestep_counter += 1
i = callback.timestep_counter
Expand All @@ -521,7 +532,7 @@ function SpeedyWeather.finish!(
callback::GlobalDiagnostics,
progn::PrognosticVariables,
diagn::DiagnosticVariables,
model::ModelSetup,
model::AbstractModel,
)
n_timesteps = callback.timestep_counter

Expand Down
19 changes: 11 additions & 8 deletions docs/src/callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ function SpeedyWeather.initialize!(
callback::StormChaser,
progn::PrognosticVariables,
diagn::DiagnosticVariables,
model::ModelSetup,
model::AbstractModel,
)
# allocate recorder: number of time steps (incl initial conditions) in simulation
callback.maximum_surface_wind_speed = zeros(progn.clock.n_timesteps + 1)

# where surface (=lowermost model layer) u, v on the grid are stored
(; u_grid, v_grid) = diagn.layers[diagn.nlev].grid_variables

u_grid = diagn.grid.u_grid[:, diagn.nlayers]
v_grid = diagn.grid.u_grid[:, diagn.nlayers]

# maximum wind speed of initial conditions
callback.maximum_surface_wind_speed[1] = max_2norm(u_grid, v_grid)

Expand Down Expand Up @@ -116,15 +117,16 @@ function SpeedyWeather.callback!(
callback::StormChaser,
progn::PrognosticVariables,
diagn::DiagnosticVariables,
model::ModelSetup,
model::AbstractModel,
)

# increase counter
callback.timestep_counter += 1
i = callback.timestep_counter

# where surface (=lowermost model layer) u, v on the grid are stored
(; u_grid, v_grid) = diagn.layers[diagn.nlev].grid_variables
u_grid = diagn.grid.u_grid[:, diagn.nlayers]
v_grid = diagn.grid.u_grid[:, diagn.nlayers]

# maximum wind speed at current time step
callback.maximum_surface_wind_speed[i] = max_2norm(u_grid, v_grid)
Expand Down Expand Up @@ -317,15 +319,16 @@ function SpeedyWeather.callback!(
callback::MyScheduledCallback,
progn::PrognosticVariables,
diagn::DiagnosticVariables,
model::ModelSetup,
model::AbstractModel,
)
# scheduled callbacks start with this line to execute only when scheduled!
# else escape immediately
isscheduled(callback.schedule, progn.clock) || return nothing

# Just print the North Pole surface temperature to screen
(;time) = progn.clock
temp_at_north_pole = diagn.layers[end].grid_variables.temp_grid[1]
temp_at_north_pole = diagn.grid.temp_grid[1,end]

@info "North pole has a temperature of $temp_at_north_pole on $time."
end

Expand All @@ -349,7 +352,7 @@ is no periodically reoccuring schedule, only `schedule.times` would include some
for events that are scheduled. Now let's create a primitive equation model with that callback

```@example schedule
spectral_grid = SpectralGrid(trunc=31, nlev=5)
spectral_grid = SpectralGrid(trunc=31, nlayers=5)
model = PrimitiveWetModel(;spectral_grid)
model.feedback.verbose = false # hide to progress meter
add!(model.callbacks, north_pole_temp_at_noon_jan9)
Expand Down
Loading