Skip to content

Commit

Permalink
Merge branch 'main' into mk/josspaper
Browse files Browse the repository at this point in the history
  • Loading branch information
milankl authored May 20, 2024
2 parents 58d582b + c30ea26 commit f40d6ce
Show file tree
Hide file tree
Showing 98 changed files with 6,708 additions and 2,549 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ jobs:
strategy:
matrix:
version:
# - '1.8'
# - '1.9'
- '1.9'
- '1.10'
os:
- ubuntu-latest
arch:
- x64
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v1
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/CompatHelper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
run: which julia
continue-on-error: true
- name: Install Julia, but only if it is not already available in the PATH
uses: julia-actions/setup-julia@v1
uses: julia-actions/setup-julia@v2
with:
version: '1'
arch: ${{ runner.arch }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/julianightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v1
- uses: julia-actions/setup-julia@v2
with:
version: nightly
arch: x64
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ deps/src/
docs/build/
docs/site/

# PythonCall added .CondaPkg to /docs
# PythonCall added .CondaPkg to /docs
docs/.CondaPkg

# File generated by Pkg, the package manager, based on a corresponding Project.toml
Expand Down
29 changes: 21 additions & 8 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SpeedyWeather"
uuid = "9e226e20-d153-4fed-8a5b-493def4f21a9"
authors = ["Milan Klöwer and SpeedyWeather contributors"]
version = "0.9"
version = "0.9.0"

[deps]
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
Expand All @@ -15,6 +15,7 @@ DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
FLoops = "cc61a311-1640-44b5-9fba-1b764f453329"
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
GPUArrays = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
GenericFFT = "a8297547-1b15-4a5a-a998-a2ac5f1cef28"
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
Expand All @@ -28,34 +29,46 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"

[weakdeps]
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb"

[extensions]
SpeedyWeatherMakieExt = "Makie"
SpeedyWeatherJLArraysExt = "JLArrays"

[compat]
AbstractFFTs = "1"
Adapt = "3, 4"
AssociatedLegendrePolynomials = "1"
BitInformation = "0.6"
CUDA = "4, 5"
CodecZlib = "0.7"
Dates = "1.8"
Dates = "1.9"
DocStringExtensions = "0.9"
FFTW = "1"
FLoops = "0.2"
FastGaussQuadrature = "0.4, 0.5, 1"
GPUArrays = "10"
GenericFFT = "0.1"
JLArrays = "0.1.4"
JLD2 = "0.4"
KernelAbstractions = "0.9"
LinearAlgebra = "1.8"
LinearAlgebra = "1.9"
Makie = "0.20, 0.21"
NCDatasets = "0.12, 0.13, 0.14"
Primes = "0.5"
Printf = "1.8"
Printf = "1.9"
ProgressMeter = "1.7"
Random = "1.8"
Statistics = "1.8"
Random = "1.9"
Statistics = "1.9"
TOML = "1"
UnicodePlots = "3.3"
julia = "1.8"
julia = "1.9"

[extras]
JLArrays = "27aeb0d3-9eb9-45fb-866b-73c2ecf80fcb"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["Test", "JLArrays"]
37 changes: 28 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ components and parameter choices; not too complicated to implement and understan
Finding a good balance is difficult but we try our best.

This means in practice, that while SpeedyWeather is currently developed, many more physical processes
and other featuers will be implemented. On our TODO is
and other features will be implemented. On our TODO is

- A (somewhat) realistic radiation scheme with a daily cycle, depending on clouds and humidity
- Longwave radiation that depends on (global) CO2 concentrations to represent climate change
Expand All @@ -72,13 +72,17 @@ about dos and don'ts. Just express your interest to contribute and we'll be happ

## Example use

The interface to SpeedyWeather.jl consist of 4 steps: define the grid, create the model, initialize, run
For a more comprehensive tutorial with several examples, see
[Examples](https://speedyweather.github.io/SpeedyWeather.jl/dev/examples_2D/) in the documentation.
The interface to SpeedyWeather.jl consist of 5 steps: define the grid, create model components,
construct the model, initialize, run

```julia
spectral_grid = SpectralGrid(trunc=31, Grid=OctahedralGaussianGrid, nlev=8)
model = PrimitiveWetModel(; spectral_grid, orography = EarthOrography(spectral_grid))
simulation = initialize!(model)
run!(simulation, period=Day(10), output=true)
spectral_grid = SpectralGrid(trunc=31, nlev=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
run!(simulation, period=Day(10), output=true) # aaaand action!
```
and you will see

Expand All @@ -98,8 +102,14 @@ section of the [documentation](https://speedyweather.github.io/SpeedyWeather.jl/

## Gallery

Here is video of some relative vorticity in the shallow water model, simulated at T1023 spectral resolution
(about 10km) on an
Specific humidity in the primitive equation model simulated at T340 spectral resolution (about 40km)
with 16 vertical levels (shown here is level 15, just above the surface) on the octahedral Gaussian grid
computed in single precision multi-threaded on 16 CPUs. With convection, large-scale condensation, surface fluxes
and some simplified radiation (the daily cycle is visible)

https://github.com/SpeedyWeather/SpeedyWeather.jl/assets/25530332/614f04cf-5080-4c89-9fd6-35efd54103a7

Relative vorticity in the shallow water model, simulated at T1023 spectral resolution (about 10km) on an
[octahedral Clenshaw-Curtis grid](https://speedyweather.github.io/SpeedyWeather.jl/dev/grids/#Implemented-grids)
with more than 4 million grid points

Expand Down Expand Up @@ -169,14 +179,23 @@ check out their documentation: [RingGrids](https://speedyweather.github.io/Speed

SpeedyWeather.jl is registered in Julia's registry, so open the package manager with `]` and
```julia
(@v1.8) pkg> add SpeedyWeather
(@v1.10) pkg> add SpeedyWeather
```
which will install the [latest release]([url](https://github.com/SpeedyWeather/SpeedyWeather.jl/releases))
and all dependencies automatically. For more information see the
[Installation](https://speedyweather.github.io/SpeedyWeather.jl/dev/installation/) in the documentation.
Please use the current minor version of Julia,
compatibilities with older versions are not guaranteed.

## Benchmarks

The primitive equations at 400km resolution with 8 vertical layers are simulated by
SpeedyWeather.jl at about 500 simulated years per day, i.e. one year takes about
3min single-threaded on a CPU. Multi-threading will increase the speed typically by 2-4x.

For an overview of typical simulation speeds a user can expect under different model setups see
[Benchmarks](https://github.com/SpeedyWeather/SpeedyWeather.jl/blob/main/benchmark).

## Copyright and license

Copyright (c) 2020 Milan Klöwer for SpeedyWeather.jl
Expand Down
121 changes: 121 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Benchmarks

created for SpeedyWeather.jl v0.9.0 on Tue, 02 Apr 2024 14:05:51.

All simulations have been benchmarked over several seconds (wallclock time) without output. Benchmarking excludes initialization and is started just before the main time loop and finishes right after. The benchmarking results here are not very robust, timings that change with +-50% are not uncommon. Proper benchmarking for performance optimization uses the minimum or median of many executions, while we run a simulation for several time steps which effectively represents the mean, susceptible to outliers that slow down the simulation. However, this is what a user will experience in most situations anyway and the following therefore presents a rough idea of how fast a SpeedyWeather simulation will run, and how much memory it requires.

### Machine details

All benchmark simulation were single-threaded on a CPU:
```julia
julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: macOS (x86_64-apple-darwin22.4.0)
CPU: 8 × Intel(R) Core(TM) i5-1030NG7 CPU @ 1.10GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-15.0.7 (ORCJIT, icelake-client)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)
Environment:
LD_LIBRARY_PATH = /Users/milan/.julia/conda/3/lib:
```

### Explanation

Abbreviations in the tables below are as follows, omitted columns use defaults.
- NF: Number format, default: Float32
- T: Spectral resolution, maximum degree of spherical harmonics, default: T31
- L: Number of vertical layers, default: 8 (for 3D models)
- Grid: Horizontal grid, default: OctahedralGaussianGrid
- Rings: Grid-point resolution, number of latitude rings pole to pole
- Dynamics: With dynamics?, default: true
- Physics: With physical parameterizations?, default: true (for primitive equation models)
- Δt: time step [s].
- SYPD: Speed of simulation, simulated years per wallclock day.
- Memory: Memory footprint of simulation, variables and constants.

### Running the benchmarks

The benchmark suite here can be reproduced by executing:

```> julia manual_benchmarking.jl```

inside `the SpeedyWeather.jl/benchmark` folder. It will create this `README.md` which can be pushed to the repository for updates or comparison.
## Models, default setups

| Model | T | L | Physics | Δt | SYPD | Memory|
| - | - | - | - | - | - | - |
| BarotropicModel | 31 | 1 | false | 1800 | 19349 | 1.22 MB |
| ShallowWaterModel | 31 | 1 | false | 1800 | 10195 | 1.24 MB |
| PrimitiveDryModel | 31 | 8 | true | 1800 | 530 | 3.95 MB |
| PrimitiveWetModel | 31 | 8 | true | 1800 | 399 | 4.28 MB |

## Grids

| Model | T | L | Grid | Rings | Δt | SYPD | Memory|
| - | - | - | - | - | - | - | - |
| PrimitiveWetModel | 63 | 8 | FullGaussianGrid | 96 | 900 | 35 | 22.50 MB |
| PrimitiveWetModel | 63 | 8 | FullClenshawGrid | 95 | 900 | 34 | 22.29 MB |
| PrimitiveWetModel | 63 | 8 | OctahedralGaussianGrid | 96 | 900 | 45 | 15.34 MB |
| PrimitiveWetModel | 63 | 8 | OctahedralClenshawGrid | 95 | 900 | 54 | 15.12 MB |
| PrimitiveWetModel | 63 | 8 | HEALPixGrid | 95 | 900 | 77 | 11.46 MB |
| PrimitiveWetModel | 63 | 8 | OctaHEALPixGrid | 95 | 900 | 56 | 13.67 MB |

## Primitive wet model, resolution

| Model | T | L | Rings | Δt | SYPD | Memory|
| - | - | - | - | - | - | - |
| PrimitiveWetModel | 31 | 8 | 48 | 1800 | 378 | 4.28 MB |
| PrimitiveWetModel | 42 | 8 | 64 | 1350 | 161 | 7.22 MB |
| PrimitiveWetModel | 63 | 8 | 96 | 900 | 47 | 15.34 MB |
| PrimitiveWetModel | 85 | 8 | 128 | 675 | 20 | 26.73 MB |
| PrimitiveWetModel | 127 | 8 | 192 | 450 | 6 | 59.10 MB |
| PrimitiveWetModel | 170 | 8 | 256 | 338 | 2 | 105.37 MB |

## PrimitiveWetModel: Physics or dynamics only

| Model | T | L | Dynamics | Physics | Δt | SYPD | Memory|
| - | - | - | - | - | - | - | - |
| PrimitiveWetModel | 31 | 8 | true | true | 1800 | 322 | 4.28 MB |
| PrimitiveWetModel | 31 | 8 | true | false | 1800 | 587 | 4.28 MB |
| PrimitiveWetModel | 31 | 8 | false | true | 1800 | 527 | 4.28 MB |

## Shallow water model, resolution

| Model | T | L | Rings | Δt | SYPD | Memory|
| - | - | - | - | - | - | - |
| ShallowWaterModel | 31 | 1 | 48 | 1800 | 9402 | 1.24 MB |
| ShallowWaterModel | 42 | 1 | 64 | 1350 | 4034 | 2.13 MB |
| ShallowWaterModel | 63 | 1 | 96 | 900 | 1132 | 4.71 MB |
| ShallowWaterModel | 85 | 1 | 128 | 675 | 415 | 8.45 MB |
| ShallowWaterModel | 127 | 1 | 192 | 450 | 105 | 19.60 MB |
| ShallowWaterModel | 170 | 1 | 256 | 338 | 39 | 36.41 MB |
| ShallowWaterModel | 255 | 1 | 384 | 225 | 9 | 89.44 MB |

## Primitive Equation, Float32 vs Float64

| Model | NF | T | L | Δt | SYPD | Memory|
| - | - | - | - | - | - | - |
| PrimitiveWetModel | Float32 | 31 | 8 | 1800 | 317 | 4.28 MB |
| PrimitiveWetModel | Float64 | 31 | 8 | 1800 | 343 | 8.03 MB |

## PrimitiveDryModel: Physics or dynamics only

| Model | T | L | Dynamics | Physics | Δt | SYPD | Memory|
| - | - | - | - | - | - | - | - |
| PrimitiveDryModel | 31 | 8 | true | true | 1800 | 462 | 3.95 MB |
| PrimitiveDryModel | 31 | 8 | true | false | 1800 | 657 | 3.95 MB |
| PrimitiveDryModel | 31 | 8 | false | true | 1800 | 683 | 3.95 MB |

## Number of vertical layers

| Model | T | L | Δt | SYPD | Memory|
| - | - | - | - | - | - |
| PrimitiveWetModel | 31 | 4 | 1800 | 583 | 2.92 MB |
| PrimitiveWetModel | 31 | 8 | 1800 | 345 | 4.28 MB |
| PrimitiveWetModel | 31 | 12 | 1800 | 217 | 5.65 MB |
| PrimitiveWetModel | 31 | 16 | 1800 | 186 | 7.03 MB |
63 changes: 63 additions & 0 deletions benchmark/benchmark_suite.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Base.@kwdef mutable struct BenchmarkSuite
title::String
nruns::Int = 1
model::Vector = fill(PrimitiveWetModel, nruns)
NF::Vector = fill(SpeedyWeather.DEFAULT_NF, nruns)
trunc::Vector{Int} = fill(SpeedyWeather.DEFAULT_TRUNC, nruns)
nlev::Vector{Int} = default_nlev(model)
Grid::Vector = fill(SpeedyWeather.DEFAULT_GRID, nruns)
nlat::Vector{Int} = fill(0, nruns)
dynamics::Vector{Bool} = fill(true, nruns)
physics::Vector{Bool} = fill(true, nruns)
SYPD::Vector{Float64} = fill(0.0, nruns)
Δt::Vector{Float64} = fill(0.0, nruns)
memory::Vector{Int} = fill(0, nruns)
end

default_nlev(::Type{<:Barotropic}) = 1
default_nlev(::Type{<:ShallowWater}) = 1
default_nlev(::Type{<:PrimitiveEquation}) = 8
default_nlev(models) = [default_nlev(model) for model in models]

# this should return number of timesteps so that every simulation
# only takes seconds
n_timesteps(trunc, nlev) = max(10, round(Int, 4e8/trunc^3/nlev^2))

function run_benchmark_suite!(suite::BenchmarkSuite)
for i in 1:suite.nruns

# unpack
Model = suite.model[i]
NF = suite.NF[i]
trunc = suite.trunc[i]
nlev = suite.nlev[i]
Grid = suite.Grid[i]
dynamics = suite.dynamics[i]
physics = suite.physics[i]

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

model = Model(;spectral_grid)
if Model <: PrimitiveEquation
model.physics = physics
model.dynamics = dynamics
else
suite.dynamics[i] = true
suite.physics[i] = false
end

simulation = initialize!(model)
suite.memory[i] = Base.summarysize(simulation)

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

time_elapsed = model.feedback.progress_meter.tlast - model.feedback.progress_meter.tinit
sypd = model.time_stepping.Δt_sec*nsteps / (time_elapsed * 365.25)

suite.Δt[i] = model.time_stepping.Δt_sec
suite.SYPD[i] = sypd
end
end
Loading

0 comments on commit f40d6ce

Please sign in to comment.