Skip to content

Variables ​

At the top of SpeedyWeather's type tree sits the Simulation, containing Variables and model (e.g. BarotropicModel), which in itself contains model components with their own fields and so on, see Models.

The variables are split into

  • groups: prognostic, grid, tendencies, dynamics, parameterizations, particles and scratch

  • namespace, these are optional sub-categories, e.g. prognostic.land and prognostic.ocean

Such that their paths are fully defined by

julia
simulation.variables.group.namespace.name  # if they are in a namespace
simulaiton.variables.group.name            # otherwise

Where to find the variables can quickly get complicated at that degre of nesting. The following is to give users a better overview of how simulation, variables and model are structured within SpeedyWeather.

Simulation ​

Let's start at the top. When creating a Simulation, its fields are

julia
using SpeedyWeather
spectral_grid = SpectralGrid(nlayers = 1)
model = BarotropicModel(spectral_grid)
simulation = initialize!(model)
Simulation{...} (725.80 KB)
├ variables::Variables{...} (139.01 KB)
└ model::BarotropicModel{...} (607.30 KB)

the variables contain all arrays but also the clock or other scalars that are supposed to be variable, so changing while a simulation is running. Note that the variables depend on what variables are requested by the model and its components, see Variables and Variable system for more information.

In contrast, we largely think of model as being constant after initialization. This is not completely true, as model does contain mutuable structs but mostly for output and feedback. Values that would influence the variables are considered read-only after initialization but there is no hard restriction on this, e.g. you can use Intrusive callbacks to change the model during integration.

The Variables struct ​

All simulation variables (prognostic and diagnostic) are stored in simulation.variables, which is a Variables struct with 7 (hardcoded) groups prognostic, grid, tendencies, dynamics, parameterizations, particles and scratch. The variables are model-specific, each model only allocates the variables it needs. The prognostic variables in variables.prognostic are generally in spectral coefficients, variables.grid hold gridded variables, variables.tendencies the tendencies, variables.dynamics work arrays that are computed by the dynamical core. variables.parameterizations are those required by the parameterizations and variables.particles by particle advection. variables.scratch are scratch arrays: These can be used in any computation by should be considered in an undefined state, so write to it before you read from it. Any other component can leave this in any state. But you can use them to avoid allocations and hold intermediate results.

A full overview of all variables can be easily printed with:

julia
simulation.variables
Variables{@NamedTuple{...}, ...} (139.01 KB)
├ prognostic (92 bytes)
│ ├ clock: Clock{DateTime, Second, Float32, Int64, Millisecond}
│ ├ scale: Base.RefValue{Float32}
│ └ vorticity: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
├ grid (0 bytes)
│ ├ vorticity: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3}...
│ ├ u: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ └ v: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
├ tendencies (21.74 KB)
│ ├ vorticity: 560×1×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ └ grid
│   ├ vorticity: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, ...
│   ├ u: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│   └ v: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
├ dynamics (0 bytes)
│ ├ u_tendency: 560×1×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ └ v_tendency: 560×1×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
├ parameterizations (0 bytes)
├ particles (0 bytes)
├ scratch (22.13 KB)
│ ├ a: 560×1 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ b: 560×1 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ └ transform_memory: 57×1×24×2 ScratchMemory{Array{ComplexF32,...}, ...}
└ fused (95.05 KB)
  ├ spectral_tendencies: 560×2×2 (LMZT) LowerTriangularArray{ComplexF32, 3,...
  ├ prognostic: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
  ├ grid_tendencies: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Float...
  ├ grid: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as A...
  ├ uv_dpres_grad_grid: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Fl...
  └ uv_dpres_grad_spectral: 560×2 (LMZ) LowerTriangularArray{ComplexF32, 2,...

These are the default variables of the BarotropicModel, for the ShallowWaterModel we have

julia
spectral_grid = SpectralGrid(nlayers = 1)
model = ShallowWaterModel(spectral_grid)
simulation = initialize!(model)
simulation.variables
Variables{@NamedTuple{...}, ...} (301.92 KB)
├ prognostic (92 bytes)
│ ├ clock: Clock{DateTime, Second, Float32, Int64, Millisecond}
│ ├ scale: Base.RefValue{Float32}
│ ├ vorticity: 560×1×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ ├ divergence: 560×1×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ └ η: 560×2 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
├ grid (0 bytes)
│ ├ vorticity: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3}...
│ ├ u: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ ├ v: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ ├ divergence: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3...
│ └ η: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as Array o...
├ tendencies (56.26 KB)
│ ├ vorticity: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ ├ divergence: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ η: 560×2 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ └ grid
│   ├ vorticity: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, ...
│   ├ u: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│   ├ v: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│   ├ divergence: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│   └ η: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as Array...
├ dynamics (12.72 KB)
│ ├ u_tendency: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ v_tendency: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ geopotential: 3168×1, 48-ring (XYZ) OctahedralGaussianField{Float32, 2}...
│ ├ kinetic_energy: 560×1×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Arra...
│ ├ uh: 560×1 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ vh: 560×1 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ └ grid
│   ├ kinetic_energy: 3168×1×1, 48-ring (XYZT) OctahedralGaussianField{Floa...
│   ├ uh: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as Arra...
│   └ vh: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as Arra...
├ parameterizations (0 bytes)
├ particles (0 bytes)
├ scratch (47.57 KB)
│ ├ a: 560×1 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ b: 560×1 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ transform_memory: 57×1×24×2 ScratchMemory{Array{ComplexF32,...}, ...}
│ └ grid
│   ├ a: 3168×1, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array...
│   └ b: 3168×1, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array...
└ fused (185.29 KB)
  ├ spectral_tendencies: 560×5×1 (LMZT) LowerTriangularArray{ComplexF32, 3,...
  ├ prognostic: 560×3×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
  ├ grid_tendencies: 3168×5×1, 48-ring (XYZT) OctahedralGaussianField{Float...
  ├ grid: 3168×3×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as A...
  ├ uv_dpres_grad_grid: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Fl...
  └ uv_dpres_grad_spectral: 560×2 (LMZ) LowerTriangularArray{ComplexF32, 2,...

The PrimitiveDryModel has the following default variables

julia
spectral_grid = SpectralGrid(nlayers = 8)
model = PrimitiveDryModel(spectral_grid)
simulation = initialize!(model)
simulation.variables
Variables{@NamedTuple{...}, ...} (4.03 MB)
├ prognostic (50.93 KB)
│ ├ clock: Clock{DateTime, Second, Float32, Int64, Millisecond}
│ ├ scale: Base.RefValue{Float32}
│ ├ vorticity: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ ├ divergence: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ temperature: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{....
│ ├ pressure: 560×2 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ land
│ │ └ soil_temperature: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Fl...
│ └ ocean
│   ├ sea_surface_temperature: 3168×1, 48-ring (XYT) OctahedralGaussianFiel...
│   └ sea_ice_concentration: 3168×1, 48-ring (XYT) OctahedralGaussianField{...
├ grid (0 bytes)
│ ├ vorticity: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3}...
│ ├ u: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ ├ v: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ ├ divergence: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3...
│ ├ temperature: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, ...
│ └ pressure: 3168×2, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as ...
├ tendencies (325.50 KB)
│ ├ vorticity: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ ├ divergence: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ temperature: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{....
│ ├ pressure: 560×1 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ grid
│ │ ├ vorticity: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, ...
│ │ ├ u: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│ │ ├ v: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│ │ ├ divergence: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│ │ ├ temperature: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32...
│ │ └ pressure: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2} a...
│ ├ land
│ │ └ soil_temperature: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Fl...
│ └ ocean
│   ├ sea_surface_temperature: 3168×1, 48-ring (XYT) OctahedralGaussianFiel...
│   └ sea_ice_concentration: 3168×1, 48-ring (XYT) OctahedralGaussianField{...
├ dynamics (621.62 KB)
│ ├ u_tendency: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ v_tendency: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ uT_anomaly: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ vT_anomaly: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ kinetic_energy: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Arra...
│ ├ dpres_dx: 3168×2, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as ...
│ ├ dpres_dy: 3168×2, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as ...
│ ├ dpres_dx_spec: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Arr...
│ ├ dpres_dy_spec: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Arr...
│ ├ pres_flux: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as...
│ ├ virtual_temperature: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, Ar...
│ ├ u_mean_grid: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32...
│ ├ v_mean_grid: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32...
│ ├ div_mean_grid: 3168-element, 48-ring (XY) OctahedralGaussianField{Float...
│ ├ div_mean: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Array{.....
│ ├ div_sum_above: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2...
│ ├ pres_flux_sum_above: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Floa...
│ ├ w: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array o...
│ ├ geopotential: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2}...
│ ├ spectral_geopotential: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, ...
│ ├ average_temperature_profile: 8-element Vector{Float32}
│ └ grid
│   ├ uT_anomaly: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│   ├ vT_anomaly: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│   └ kinetic_energy: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Floa...
├ parameterizations (381.36 KB)
│ ├ surface_pressure: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ ├ surface_shortwave_down: 3168-element, 48-ring (XY) OctahedralGaussianFi...
│ ├ surface_longwave_down: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ cos_zenith: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32,...
│ ├ albedo: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1} ...
│ ├ surface_roughness: 3168-element, 48-ring (XY) OctahedralGaussianField{F...
│ ├ boundary_layer_drag: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ ├ boundary_layer_height: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ surface_wind_speed: 3168-element, 48-ring (XY) OctahedralGaussianField{...
│ ├ surface_air_density: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ ├ surface_air_temperature: 3168-element, 48-ring (XY) OctahedralGaussianF...
│ ├ sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaussianField{...
│ ├ surface_shortwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│ ├ outgoing_shortwave: 3168-element, 48-ring (XY) OctahedralGaussianField{...
│ ├ surface_longwave_up: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ ├ outgoing_longwave: 3168-element, 48-ring (XY) OctahedralGaussianField{F...
│ ├ land
│ │ ├ surface_shortwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFi...
│ │ ├ surface_longwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ │ ├ sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│ │ ├ albedo: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1...
│ │ ├ surface_roughness: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ │ └ surface_shortwave_down: 3168-element, 48-ring (XY) OctahedralGaussian...
│ └ ocean
│   ├ surface_shortwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFi...
│   ├ surface_longwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│   ├ surface_humidity_flux: 3168-element, 48-ring (XY) OctahedralGaussianF...
│   ├ surface_sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaus...
│   ├ albedo: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1...
│   ├ surface_roughness: 3168-element, 48-ring (XY) OctahedralGaussianField...
│   ├ sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│   └ surface_shortwave_down: 3168-element, 48-ring (XY) OctahedralGaussian...
├ particles (0 bytes)
├ scratch (412.77 KB)
│ ├ a: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ b: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ a_2D: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Array{...}}
│ ├ b_2D: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Array{...}}
│ ├ transform_memory: 57×8×24×2 ScratchMemory{Array{ComplexF32,...}, ...}
│ └ grid
│   ├ a: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array...
│   ├ b: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array...
│   ├ a_2D: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1} ...
│   └ b_2D: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1} ...
└ fused (2.24 MB)
  ├ spectral_tendencies: 560×49×1 (LMZT) LowerTriangularArray{ComplexF32, 3...
  ├ prognostic: 560×25×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{....
  ├ grid_tendencies: 3168×49×1, 48-ring (XYZT) OctahedralGaussianField{Floa...
  ├ grid: 3168×25×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as ...
  ├ uv_dpres_grad_grid: 3168×18×2, 48-ring (XYZT) OctahedralGaussianField{F...
  └ uv_dpres_grad_spectral: 560×18 (LMZ) LowerTriangularArray{ComplexF32, 2...

And the most complex model, the PrimitiveWetModel allocates

julia
spectral_grid = SpectralGrid(nlayers = 8)
model = PrimitiveWetModel(spectral_grid)
simulation = initialize!(model)
simulation.variables
Variables{@NamedTuple{...}, ...} (5.04 MB)
├ prognostic (89.05 KB)
│ ├ clock: Clock{DateTime, Second, Float32, Int64, Millisecond}
│ ├ scale: Base.RefValue{Float32}
│ ├ vorticity: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ ├ divergence: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ temperature: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{....
│ ├ pressure: 560×2 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ humidity: 560×8×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{...}...
│ ├ land
│ │ ├ soil_temperature: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Fl...
│ │ ├ soil_moisture: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Float...
│ │ └ snow_depth: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2}...
│ └ ocean
│   ├ sea_surface_temperature: 3168×1, 48-ring (XYT) OctahedralGaussianFiel...
│   └ sea_ice_concentration: 3168×1, 48-ring (XYT) OctahedralGaussianField{...
├ grid (0 bytes)
│ ├ vorticity: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3}...
│ ├ u: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ ├ v: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Arra...
│ ├ divergence: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3...
│ ├ temperature: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, ...
│ ├ pressure: 3168×2, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as ...
│ └ humidity: 3168×8×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} ...
├ tendencies (363.62 KB)
│ ├ vorticity: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{......
│ ├ divergence: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ temperature: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{....
│ ├ pressure: 560×1 (LMT) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ humidity: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{...}...
│ ├ grid
│ │ ├ vorticity: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, ...
│ │ ├ u: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│ │ ├ v: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as Ar...
│ │ ├ divergence: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│ │ ├ temperature: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32...
│ │ ├ pressure: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2} a...
│ │ └ humidity: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3...
│ ├ land
│ │ ├ soil_temperature: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Fl...
│ │ ├ soil_moisture: 3168×2×1, 48-ring (XYZT) OctahedralGaussianField{Float...
│ │ └ snow_depth: 3168×1, 48-ring (XYT) OctahedralGaussianField{Float32, 2}...
│ └ ocean
│   ├ sea_surface_temperature: 3168×1, 48-ring (XYT) OctahedralGaussianFiel...
│   └ sea_ice_concentration: 3168×1, 48-ring (XYT) OctahedralGaussianField{...
├ dynamics (621.62 KB)
│ ├ u_tendency: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ v_tendency: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ uT_anomaly: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ vT_anomaly: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{.....
│ ├ kinetic_energy: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Arra...
│ ├ dpres_dx: 3168×2, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as ...
│ ├ dpres_dy: 3168×2, 48-ring (XYT) OctahedralGaussianField{Float32, 2} as ...
│ ├ dpres_dx_spec: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Arr...
│ ├ dpres_dy_spec: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Arr...
│ ├ pres_flux: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as...
│ ├ virtual_temperature: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, Ar...
│ ├ u_mean_grid: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32...
│ ├ v_mean_grid: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32...
│ ├ div_mean_grid: 3168-element, 48-ring (XY) OctahedralGaussianField{Float...
│ ├ div_mean: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Array{.....
│ ├ div_sum_above: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2...
│ ├ pres_flux_sum_above: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Floa...
│ ├ w: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array o...
│ ├ uq: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{...}}
│ ├ vq: 560×8×1 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{...}}
│ ├ geopotential: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2}...
│ ├ spectral_geopotential: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, ...
│ ├ average_temperature_profile: 8-element Vector{Float32}
│ └ grid
│   ├ uT_anomaly: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│   ├ vT_anomaly: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32,...
│   ├ kinetic_energy: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Floa...
│   ├ uq: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as A...
│   └ vq: 3168×8×1, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as A...
├ parameterizations (635.60 KB)
│ ├ surface_pressure: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ ├ surface_shortwave_down: 3168-element, 48-ring (XY) OctahedralGaussianFi...
│ ├ surface_longwave_down: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ rain_rate: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, ...
│ ├ cos_zenith: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32,...
│ ├ albedo: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1} ...
│ ├ surface_roughness: 3168-element, 48-ring (XY) OctahedralGaussianField{F...
│ ├ boundary_layer_drag: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ ├ boundary_layer_height: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ surface_wind_speed: 3168-element, 48-ring (XY) OctahedralGaussianField{...
│ ├ surface_air_density: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ ├ surface_air_temperature: 3168-element, 48-ring (XY) OctahedralGaussianF...
│ ├ sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaussianField{...
│ ├ surface_humidity_flux: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ rain_large_scale: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ ├ snow_large_scale: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ ├ rain_rate_large_scale: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ snow_rate_large_scale: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ ├ snow_rate: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, ...
│ ├ cloud_top: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, ...
│ ├ rain_convection: 3168-element, 48-ring (XY) OctahedralGaussianField{Flo...
│ ├ rain_rate_convection: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│ ├ snow_convection: 3168-element, 48-ring (XY) OctahedralGaussianField{Flo...
│ ├ snow_rate_convection: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│ ├ surface_shortwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│ ├ outgoing_shortwave: 3168-element, 48-ring (XY) OctahedralGaussianField{...
│ ├ cloud_top_height: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ ├ cloud_cover: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32...
│ ├ surface_longwave_up: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ ├ outgoing_longwave: 3168-element, 48-ring (XY) OctahedralGaussianField{F...
│ ├ land
│ │ ├ surface_shortwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFi...
│ │ ├ surface_longwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│ │ ├ sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│ │ ├ river_runoff: 3168-element, 48-ring (XY) OctahedralGaussianField{Floa...
│ │ ├ surface_humidity_flux: 3168-element, 48-ring (XY) OctahedralGaussianF...
│ │ ├ snow_melt_rate: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ │ ├ vegetation_high: 3168-element, 48-ring (XY) OctahedralGaussianField{F...
│ │ ├ vegetation_low: 3168-element, 48-ring (XY) OctahedralGaussianField{Fl...
│ │ ├ soil_moisture_availability: 3168-element, 48-ring (XY) OctahedralGaus...
│ │ ├ albedo: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1...
│ │ ├ surface_roughness: 3168-element, 48-ring (XY) OctahedralGaussianField...
│ │ └ surface_shortwave_down: 3168-element, 48-ring (XY) OctahedralGaussian...
│ └ ocean
│   ├ surface_shortwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFi...
│   ├ surface_longwave_up: 3168-element, 48-ring (XY) OctahedralGaussianFie...
│   ├ surface_humidity_flux: 3168-element, 48-ring (XY) OctahedralGaussianF...
│   ├ surface_sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaus...
│   ├ albedo: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1...
│   ├ surface_roughness: 3168-element, 48-ring (XY) OctahedralGaussianField...
│   ├ sensible_heat_flux: 3168-element, 48-ring (XY) OctahedralGaussianFiel...
│   └ surface_shortwave_down: 3168-element, 48-ring (XY) OctahedralGaussian...
├ particles (0 bytes)
├ scratch (412.77 KB)
│ ├ a: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ b: 560×8 (LMZ) LowerTriangularArray{ComplexF32, 2, Array{...}}
│ ├ a_2D: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Array{...}}
│ ├ b_2D: 560-element, 33x32 LowerTriangularMatrix{ComplexF32, Array{...}}
│ ├ transform_memory: 57×8×24×2 ScratchMemory{Array{ComplexF32,...}, ...}
│ └ grid
│   ├ a: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array...
│   ├ b: 3168×8, 48-ring (XYZ) OctahedralGaussianField{Float32, 2} as Array...
│   ├ a_2D: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1} ...
│   └ b_2D: 3168-element, 48-ring (XY) OctahedralGaussianField{Float32, 1} ...
└ fused (2.92 MB)
  ├ spectral_tendencies: 560×73×1 (LMZT) LowerTriangularArray{ComplexF32, 3...
  ├ prognostic: 560×33×2 (LMZT) LowerTriangularArray{ComplexF32, 3, Array{....
  ├ grid_tendencies: 3168×73×1, 48-ring (XYZT) OctahedralGaussianField{Floa...
  ├ grid: 3168×33×2, 48-ring (XYZT) OctahedralGaussianField{Float32, 3} as ...
  ├ uv_dpres_grad_grid: 3168×18×2, 48-ring (XYZT) OctahedralGaussianField{F...
  └ uv_dpres_grad_spectral: 560×18 (LMZ) LowerTriangularArray{ComplexF32, 2...

Setting variables ​

The prognostic variables can be mutated (e.g. to set new initial conditions) with the SpeedyWeather.set! function. Other variables can be set too but they might be overwritten such that your changes may have a different effect than you expect. You can specify group (default =:prognostic) and namespace (default =nothing) in set! to set variables, e.g.

julia
set!(simulation, sea_surface_temperature=300, namespace=:ocean)

For another example, see Set tracers.

Step dimension ​

As you'll notice when inspecting simulation.variables is that many prognostic and tendency variables will have one more dimension than you may think they should have. This is the step dimension as many time stepping schemes require either several steps in the prognostic variables (think Leapfrog) or several tendency steps (think multi-step methods). In many cases this additional dimension will just be a trailing singleton dimension, but rather than dropping it by hand use get_step which knows which dimension is the step dimension (see below). As the step dimension essentially contains several "versions" of the same variable the error you will make by selecting the wrong one is generally small. In Leapfrog, you would simply select the previous time step for example, see Time steppers. So prognostic and tendency variables have the following dimensions in that order:

  • horizontal dimension (unravalled longitude and latitude, or degree/order of spherical harmonics)

  • vertical (optional, many 2D variables will drop this)

  • step (all Time stepped variables and tendencies have this)

What these dimensions represent is recorded in the arrays' dimension tags, see Array dimensions. The step dimension is tagged as time T, so a spectral prognostic variable with vertical layers and a step dimension shows (LMZT) in its array summary, its grid-space equivalent (XYZT).

So a conceptually 2D horizontal-only variable may use an array of

  • one dimesion (unravelled horizontal dimension),

  • two dimensions (trailing singleton dimension for the vertical),

  • two dimensions (trailing dimension for the step),

  • or three dimesions (singleton dimension for the vertical, and dimension for step)

and similar with 3D variables (but the vertical dimension isn't singleton then). Whether the step dimension is singleton or not depends on the time stepping scheme in use.

To ease the selection of the step dimension use the get_step function. It always selects the dimension tagged as time T, so you do not have to work out yourself whether a given array's 2nd dimension is the vertical or the step. Called without a step index it creates a view onto the array selecting the last step, as this in many cases represents the "current" step and not any previous ones. But this depends on your time stepping scheme (which the variable itself does not know about). For example

julia
size(simulation.variables.grid.u)

is a 3D array representing a 3D variable. The array has one more dimension (the last) for the step but one less because horizontal dimensions are unravelled into one. The step dimension here has two steps which represent with Leapfrog time stepping the previous and current step, so to not select the previous time step, you should index [ij, k, 2] here. This is what the get_step function will do for you

julia
get_step(simulation.variables.grid.u)       # selects the last step index automatically
get_step(simulation.variables.grid.u, 1)    # select first step
get_step(simulation.variables.grid.u, 2)    # select 2nd step

Then you can use [ij, k] indexing afterwards again.

Because get_step goes by the time tag T and not by the position of the last dimension, it is also safe to call on variables that have no step dimension: a variable tagged XY, XYZ, LM or LMZ has nothing to select from, so the full variable is returned as a view and the step index is ignored. This means you can write get_step(var) generically without checking first whether var has steps at all. Diagnostic and working variables typically fall in this category, e.g. a ParameterizationVariable tagged XYZ whose 2nd dimension is the vertical: get_step returns the whole thing rather than mistaking a layer for a step.

The companion get_steps returns all steps as a tuple of views, one per step, which is handy when a scheme needs several of them at once:

julia
u_old, u_new = get_steps(simulation.variables.grid.u)   # Leapfrog: previous and current step

Consistently with get_step, a variable without a step dimension yields a 1-tuple holding the full variable — the vertical layers of an XYZ variable are not steps and are never splatted.

Fused variables ​

You may notice simulation.variables.fused when inspecting the variables. For performance reasons, some variables are stored as views into larger fused arrays, which stack several variables in the vertical so that, e.g., spectral transforms can be done for all of them in one batch. This is an internal implementation detail: you can treat all variables as independent and should always access them through their usual names, e.g. simulation.variables.prognostic.vorticity, not through simulation.variables.fused. See Variable fusion for details.