Core Types
This page documents the core data types in QGYBJ+.jl.
QGParams
The main parameter structure containing all simulation settings.
QGYBJplus.QGParams — Type
QGParams{T}Container for all physical and numerical parameters of the QG-YBJ+ model.
Domain Parameters
nx, ny, nz: Grid resolution in x, y, z directionsLx, Ly, Lz: Domain size in x, y, z in meters (REQUIRED - no default)x0, y0: Domain origin in x, y (default: 0, use -Lx/2,-Ly/2 for centered domain)
Time Stepping
dt: Time step sizent: Total number of time steps
Physical Parameters
f₀: Coriolis parameter (typically 1.0 for nondimensional)N²: Buoyancy frequency squared (default 1.0)W2F: DEPRECATED - no longer used (kept for backward compatibility)γ: Robert-Asselin filter coefficient (typically 10⁻³)linear_vert_structure: Legacy Fortran flag (0 or 1), typically 0
Viscosity/Hyperviscosity
The model uses two hyperdiffusion operators for stability:
νₕ, νᵥ: Legacy generic viscosity coefficients (prefer specific coefficients below)νₕ₁, ilap1: First hyperviscosity coefficient and Laplacian power for mean flowνₕ₂, ilap2: Second hyperviscosity coefficient and Laplacian power for mean flowνₕ₁ʷ, ilap1w: First hyperviscosity for wavesνₕ₂ʷ, ilap2w: Second hyperviscosity for wavesνz: Vertical diffusion coefficient
The hyperdiffusion term is: ν₁(-∇²)^ilap1 + ν₂(-∇²)^ilap2
Physics Switches
These boolean flags control different physics modes:
inviscid: If true, disable all dissipationlinear: If true, disable nonlinear advection termsno_dispersion: If true, disable wave dispersion (A=0)passive_scalar: If true, waves are passive (no dispersion, no refraction)ybj_plus: If true, use YBJ+ formulation; if false, use normal YBJno_feedback: If true, disable ALL wave-mean flow coupling (master switch)fixed_flow: If true, mean flow doesn't evolve (ψ constant in time)no_wave_feedback: If true, disable qʷ term specifically (waves don't modify PV)
Note: Wave feedback is enabled only when BOTH no_feedback=false AND no_wave_feedback=false.
Stratification Parameters (Skewed Gaussian profile)
For the skewed Gaussian N²(z) profile: N²(z) = N₁² exp(-(z-z₀)²/σ²) [1 + erf(α(z-z₀)/(σ√2))] + N₀²
N₀²_sg: Background N² (N₀²)N₁²_sg: Peak N² amplitude (N₁²)σ_sg: Width parameter (σ)z₀_sg: Center depth (z₀)α_sg: Skewness parameter (α)
Example
par = default_params(nx=128, ny=128, nz=64, Lx=500e3, Ly=500e3, Lz=4000.0, dt=0.001, nt=10000)See also: default_params, with_b_ell_profile
Fields
| Field | Type | Description |
|---|---|---|
nx, ny, nz | Int | Grid dimensions |
Lx, Ly, Lz | Float64 | Domain sizes (REQUIRED) |
dt | Float64 | Time step |
nt | Int | Number of time steps |
f₀ | Float64 | Coriolis parameter |
N² | Float64 | Buoyancy frequency squared |
γ | Float64 | Robert-Asselin filter coefficient |
ybj_plus | Bool | Use YBJ+ formulation |
no_feedback | Bool | Master switch: disable all wave-mean coupling |
no_wave_feedback | Bool | Disable wave feedback on mean flow |
inviscid | Bool | Disable all dissipation |
linear | Bool | Disable nonlinear terms |
νₕ₁ | Float64 | First hyperviscosity coefficient (flow) |
ilap1 | Int | Laplacian power for νₕ₁ |
νₕ₂ | Float64 | Second hyperviscosity coefficient (flow) |
ilap2 | Int | Laplacian power for νₕ₂ |
νₕ₁ʷ | Float64 | First hyperviscosity coefficient (waves) |
νₕ₂ʷ | Float64 | Second hyperviscosity coefficient (waves) |
νz | Float64 | Vertical diffusivity |
Note: Type Unicode characters using \ + name + <tab> in Julia REPL (e.g., f\_0<tab> → f₀)
Constructors
# Domain size is REQUIRED (no defaults)
params = default_params(Lx=500e3, Ly=500e3, Lz=4000.0) # 500km × 500km × 4km
# Custom parameters with domain size
params = default_params(;
Lx = 500e3, Ly = 500e3, Lz = 4000.0, # Domain size (REQUIRED)
nx = 128, ny = 128, nz = 64, # Grid dimensions
f₀ = 1.0,
N² = 1.0,
ybj_plus = true,
νₕ₂ = 10.0,
ilap2 = 6
)Example
# High-resolution parameters (domain size REQUIRED)
params = default_params(;
Lx = 500e3, Ly = 500e3, Lz = 4000.0,
nx = 256, ny = 256, nz = 128,
ybj_plus = true,
no_feedback = false,
νₕ₂ = 1e-12,
ilap2 = 8
)Grid
The computational grid structure.
QGYBJplus.Grid — Type
Grid{T, AT}Numerical grid and spectral metadata for the QG-YBJ+ model.
Type Parameters
T: Floating point type (typically Float64)AT: Array type for 2D arrays (Array{T,2} or PencilArray{T,2})
Fields
Grid Dimensions
nx, ny, nz::Int: Number of grid points in x, y, z directionsLx, Ly, Lz::T: Domain size in x, y, z in meters (REQUIRED - no default)x0, y0::T: Domain origin in x, y (0 = standard [0,Lx), -Lx/2 = centered [-Lx/2,Lx/2))dx, dy::T: Grid spacing in x, y (computed as Lx/nx, Ly/ny)
Vertical Grid
z::Vector{T}: Staggered (cell-centered) vertical levels, length nzdz::Vector{T}: Layer thicknesses between levels, length nz-1 (or length 1 containing Lz when nz=1)
Spectral Wavenumbers
kx::Vector{T}: x-wavenumbers following FFTW convention, length nxky::Vector{T}: y-wavenumbers following FFTW convention, length nykh2::AT: Horizontal wavenumber squared kx² + ky², size (nx, ny) in serial, or a 3D PencilArray with shape (nz, nx, ny) in parallel.
Parallel Decomposition
decomp::Any: PencilArrays decomposition (nothing for serial)
Wavenumber Convention
For a domain of size L with n points:
k[i] = (2π/L) × m where m = i-1 for i ≤ (n+1)÷2
m = i-1-n for i > (n+1)÷2Example
par = default_params(nx=64, ny=64, nz=32, Lx=500e3, Ly=500e3, Lz=4000.0)
G = init_grid(par)
# G.kx[1] = 0 (mean mode)
# G.kx[33] = -32 × (2π/Lx) (most negative wavenumber)Fields
| Field | Type | Description |
|---|---|---|
nx, ny, nz | Int | Grid dimensions |
Lx, Ly, Lz | Float64 | Domain sizes |
dx, dy, dz | Float64 | Grid spacings |
x, y, z | Vector{Float64} | Coordinate arrays |
kx, ky | Vector{Float64} | Wavenumber arrays |
kh2 | Array{Float64,2} | Horizontal wavenumber squared |
Constructors
# Initialize grid from parameters (recommended)
params = default_params(Lx=500e3, Ly=500e3, Lz=4000.0, nx=64, ny=64, nz=32)
grid = init_grid(params)Grid Utilities
# Get wavenumbers at local indices (works with MPI)
kx = get_kx(grid, i) # Get kx at local index i
ky = get_ky(grid, j) # Get ky at local index j
kh2 = get_kh2(grid, i, j) # Get horizontal wavenumber squaredState
The simulation state containing all prognostic and diagnostic fields.
QGYBJplus.State — Type
State{T, RT, CT}Container for all prognostic and diagnostic fields in the QG-YBJ+ model.
Type Parameters
T: Floating point type (Float64)RT: Real array type (Array{T,3} or PencilArray{T,3})CT: Complex array type (Array{Complex{T},3} or PencilArray{Complex{T},3})
Prognostic Fields (evolved in time)
q::CT: QG potential vorticity in spectral spaceL⁺A::CT: YBJ+ wave envelope in spectral space
Diagnostic Fields (computed from prognostic)
psi::CT: Streamfunction ψ (from q via elliptic inversion)A::CT: Wave amplitude (from L⁺A via YBJ+ inversion)C::CT: Vertical derivative C = ∂A/∂z (for wave velocities)
Velocity Fields (real space)
u::RT: Zonal velocity u = -∂ψ/∂yv::RT: Meridional velocity v = ∂ψ/∂xw::RT: Vertical velocity (from omega equation or YBJ)
Array Dimensions
All arrays have shape (nz, nx, ny).
- Spectral fields (q, psi, A, L⁺A, C): Complex arrays
- Real-space fields (u, v, w): Real arrays
Physical Interpretation
The prognostic variables are:
q: Quasi-geostrophic potential vorticity
- Related to ψ by: q = ∇²ψ + (f²/N²)∂²ψ/∂z²
L⁺A: YBJ+ wave envelope
- Operator definitions (from PDF):
- L (YBJ): L = ∂/∂z(f²/N² ∂/∂z) [eq. (4)]
- L⁺ (YBJ+): L⁺ = L - k_h²/4 [spectral space]
- Key relation: L = L⁺ + kh²/4, so LA = L⁺A + (kh²/4)A
- Operator definitions (from PDF):
Example
G = init_grid(par)
S = init_state(G)
# Access fields
q_spectral = S.q # Complex (nz, nx, ny)
u_realspace = S.u # Real (nz, nx, ny)See also: init_state, Grid
Fields
Prognostic Fields (evolved in time):
| Field | Type | Description |
|---|---|---|
q | Array{ComplexF64,3} | QG potential vorticity (spectral) |
L⁺A | Array{ComplexF64,3} | YBJ+ wave envelope L⁺A where L⁺ = L - k_h²/4 (spectral) |
Diagnostic Fields (computed from prognostic):
| Field | Type | Description |
|---|---|---|
psi | Array{ComplexF64,3} | Streamfunction ψ (spectral) |
A | Array{ComplexF64,3} | Wave amplitude (spectral, from L⁺A via inversion) |
C | Array{ComplexF64,3} | Vertical derivative ∂A/∂z (spectral) |
Velocity Fields (real space):
| Field | Type | Description |
|---|---|---|
u | Array{Float64,3} | Zonal velocity u = -∂ψ/∂y |
v | Array{Float64,3} | Meridional velocity v = ∂ψ/∂x |
w | Array{Float64,3} | Vertical velocity (from omega equation) |
LA_real | Array{Float64,3} | Real part of wave velocity amplitude LA |
LA_imag | Array{Float64,3} | Imaginary part of wave velocity amplitude LA |
The leapfrog scheme uses separate State objects (Snm1, Sn, Snp1) rather than storing previous time levels within a single State struct. This design allows proper handling of MPI parallel arrays (PencilArrays).
Constructors
# Create empty state from grid
state = init_state(grid)
# Copy state (preserves PencilArray topology for MPI)
state_copy = copy_state(state)Copying States
For MPI parallel runs, always use copy_state instead of deepcopy:
# CORRECT: preserves pencil topology
Snm1 = copy_state(S)
# WRONG: breaks PencilArray transpose operations
Snm1 = deepcopy(S) # Causes "pencil topologies must be the same" errorAccessing Fields
# Prognostic field (complex, spectral)
L⁺A = state.L⁺A # size (nz, nx, ny), uses Unicode identifier
# Diagnostic fields (complex, spectral)
psi_k = state.psi # size (nz, nx, ny)
A = state.A # size (nz, nx, ny)
# Physical fields (real)
u = state.u # size (nz, nx, ny)
v = state.v # size (nz, nx, ny)
LA_real = state.LA_real # Real part of wave velocity amplitude
LA_imag = state.LA_imag # Imaginary part of wave velocity amplitudeFFT Plans
FFTW plan structures for efficient transforms.
Creating Plans
# Standard plans
plans = plan_transforms!(grid)
# With optimization
plans = plan_transforms!(grid; flags=FFTW.MEASURE)
# With threading
FFTW.set_num_threads(8)
plans = plan_transforms!(grid)Using Transforms
# Forward transform: Physical → Spectral
fft_forward!(dst, src, plans)
# Backward transform: Spectral → Physical
fft_backward!(dst, src, plans)Setup Model
The setup_model function is the recommended way to initialize all components:
par = default_params(Lx=500e3, Ly=500e3, Lz=4000.0, nx=64, ny=64, nz=32)
G, S, plans, a_ell = setup_model(par)This returns:
G: Grid structureS: State structureplans: FFT plansa_ell: Elliptic coefficient array for PV inversion
For non-constant stratification, use:
par = default_params(Lx=500e3, Ly=500e3, Lz=4000.0, stratification=:skewed_gaussian)
G, S, plans, a_ell, N2_profile = setup_model_with_profile(par)Type Hierarchy
QGParams{T} - Model parameters
Grid - Spatial grid and wavenumbers
State - Prognostic and diagnostic fieldsType Stability
All core types are fully type-stable:
using Test
@inferred init_state(grid)
@inferred leapfrog_step!(state, grid, params, plans, a_ell)Serialization
Types support JLD2 serialization:
using JLD2
# Save
@save "simulation.jld2" grid params state
# Load
@load "simulation.jld2" grid params state