API Reference
GREBClimate.DATA_DEP_NAME — Constant
Name of the DataDep, and the folder name the dataset is cached under inside DataDeps' storage (~/.julia/scratchspaces/<uuid>/datadeps/ by default).
GREBClimate.DATA_RELEASE_TAG — Constant
Release tag and asset name for the published dataset bundle.
The bundle is built from a validated greb_input_data/ tree with tools/package_dataset.jl, which also prints the SHA256 below.
GREBClimate.DATA_SHA256 — Constant
SHA256 of DATA_ARCHIVE_NAME, 370563584 bytes.
Reproducible: tools/package_dataset.jl builds the archive with sorted entries, zeroed owner/group, pinned entry timestamps and gzip -n, so the archive depends only on the dataset's contents. Regenerating the .jld2 tree from the raw .bin files and repackaging reproduces this exact hash.
(The timestamp pin matters: without it tar stored each file's mtime, so a regenerated-but-byte-identical dataset produced a different archive.)
GREBClimate.nghost — Constant
nghostPeriodic ghost cells held at each end of the longitude axis by the circulation buffers, so wrap-around is a unit-stride read instead of a gather.
A ghosted column stores A[i, k] at row i + nghost, with each end mirroring the other:
row 1 … 3 │ 4 … 99 │ 100 … 102
holds 94…96 │ 1 … 96 (real) │ 1 … 3So A[j-1, k] is just P[j+2, k]. The lon_jm1..lon_jp3 index arrays this replaced cost ~12 gather instructions per inner loop.
nghost is the zonal stencils' reach, so it is 3 and they spell their offsets out literally (j … j+6); widening the stencil means widening both.
Also called halo cells (the usual term in climate models) or guard cells. The literature covers the distributed-memory use, where ghosts cache a neighbouring MPI rank and are refreshed by a "halo exchange" - Kjolstad & Snir, "The Ghost Cell Pattern" (ParaPLoP 2010). Here there is one process and the neighbour is the opposite edge of the same array, so ghost cells buy vectorisable addressing, not avoided communication.
GREBClimate.nstep_yr — Constant
nstep_yrTime steps per year (ndays_yr * ndt_days = 730). Together with xdim and ydim this fixes the shape of every field the model steps.
julia> (xdim, ydim, nstep_yr)
(96, 48, 730)GREBClimate.xdim — Constant
Number of longitude grid points.
GREBClimate.xghost — Constant
Row count of a ghosted circulation buffer (xdim + 2nghost).
GREBClimate.ydim — Constant
Number of latitude grid points.
GREBClimate.CirculationWorkspace — Type
CirculationWorkspacePre-allocated buffers for diffusion, advection, and circulation calculations. Reused across all time steps to eliminate allocations.
GREBClimate.ClimateFields — Type
ClimateFieldsLoaded climatology, derived grid fields, flux corrections, and the regional-CO2 mask/solar table - everything load_greb_jld2! fills in and every physics function reads. One instance per greb_model! run; never shared as global state.
ClimateFields() builds an all-zero instance and leaves loaded = false; load_greb_jld2! sets loaded = true once real climatology is in place. greb_model! refuses to run unloaded fields unless explicitly told to via allow_uninitialized=true - an all-zero climatology produces a physically meaningless world pinned at the 40 K floor (~-233 °C) rather than an error, so the flag exists to keep that path opt-in.
GREBClimate.ModelState — Type
ModelStatePer-run mutable state that isn't climatology: the runtime solar-forcing multiplier (SWradiation! reads it) and the surface-temperature accumulator behind the annual progress line (diagnostics! reads/writes it). One instance per greb_model! run.
This is scratch space for the printed summary, not an output path - Tsmn is averaged, printed and zeroed within a single diagnostics! call, so it never holds a readable annual mean once the call returns. Model output is the Vector{MonthlyRecord} that greb_model! returns.
GREBClimate.MonthlyAccumulator — Type
MonthlyAccumulatorAccumulates fields over a month for monthly-mean output. Reset after each month via reset!.
GREBClimate.MonthlyRecord — Type
MonthlyRecordOne monthly-mean output record: a NamedTuple with fields Ts, Ta, To, q, albedo, ice, precip, evap, qcrcl, sw, lw, qlat, qsens, each an (xdim, ydim) Matrix{Float32}. Produced by output!; greb_model!'s ctrl/scnr results are Vector{MonthlyRecord}.
GREBClimate.PhysicsConfig — Type
PhysicsConfigAll model switches and parameters: mean-climate/CO₂-response toggles, circulation components, hydrology parameters, external-forcing flags, and the current experiment type. Passed explicitly to every physics function; build one with create_experiment_config rather than the bare keyword constructor for anything beyond :full_model.
GREBClimate.RunSpec — Type
RunSpecRun durations (in years) for greb_model!: flux (flux-correction spin-up), ctrl (control run), scnr (scenario run). A keyword struct instead of three bare positional ints, whose order was easy to swap by mistake.
julia> RunSpec(ctrl = 10, scnr = 30)
RunSpec(0, 10, 30)
julia> RunSpec().ctrl, RunSpec().scnr
(1, 1)GREBClimate.SurfaceState — Type
SurfaceStateA run's current surface/atmosphere state - Ts, Ta, To, q - passed as one argument to diagnostics!, output!, time_loop!, and qflux_correction!. A thin reference wrapper around already-allocated arrays; construct once per run/call (like ws/acc), never inside the per-timestep loop.
GREBClimate.TimeState — Type
TimeStateTracks the model's position within the current year: jday (calendar day, 1..365) and ityr (timestep-of-year, 1..nstep_yr). Mutated in place each timestep by time_loop!/qflux_correction!.
GREBClimate.LWradiation! — Method
LWradiation!(Ts, Ta, q, CO2, fields::ClimateFields, timestate, cfg::PhysicsConfig, ws::CirculationWorkspace)Computes atmospheric emissivity from CO₂/water-vapor/cloud columns, then surface/upward/downward longwave flux. If cfg.log_atmos_dmc is false, only LW_down is zeroed - LW_up is snapshotted beforehand and keeps its full value (decouples surface from atmospheric downwelling feedback without touching the atmosphere's own emission term). Returns (LW_surf, LW_up, LW_down, em).
GREBClimate.SWradiation! — Method
SWradiation!(Ts, fields::ClimateFields, state::ModelState, timestate, cfg::PhysicsConfig, ws::CirculationWorkspace)Computes ice cover, surface/atmospheric/combined albedo, and net shortwave flux from Ts and the current cloud climatology. Returns (SW, albedo, ice_cover).
GREBClimate._cached_datadep_path — Method
_cached_datadep_path() -> String or nothingPath to the already-downloaded dataset cache, or nothing if it is absent.
DataDeps offers no public "is this already here?" query - datadep"..." and resolve both fetch when the data is missing, which is the opposite of what is wanted here. try_determine_load_path is the internal function that answers it without touching the network. It is wrapped in a try so that if a future DataDeps release renames or removes it, this degrades to "not cached" (and the normal download path still works) rather than erroring.
GREBClimate._wz_for — Method
Select wz_air/wz_vapor for a scale height, erroring on anything else.
GREBClimate.advection! — Method
advection!(T1, h_scl, fields::ClimateFields, ws::CirculationWorkspace, timestate, cfg::PhysicsConfig)Meridional + zonal advection of T1 (temperature or humidity), writing the tendency into ws.dX_adv. Gated by cfg.log_hadv/cfg.log_vadv depending on h_scl.
GREBClimate.apply_dynamic_co2_mask! — Method
apply_dynamic_co2_mask!(cfg::PhysicsConfig, fields::ClimateFields, icmn_ctrl)Sets fields.co2_part for the two regional-CO₂ experiments whose mask depends on the control run's ice climatology (:regional_co2_ocean, :regional_co2_land_ice). A no-op for every other experiment - the static regional masks are set by init_model!.
GREBClimate.apply_scenario_anomalies — Method
apply_scenario_anomalies(scnr_records, ctrl_clim)::Vector{MonthlyRecord}Subtracts the matching calendar month of ctrl_clim (from build_monthly_climatology) from each record in scnr_records, turning absolute monthly output into anomalies relative to the control run.
GREBClimate.build_monthly_climatology — Method
build_monthly_climatology(records::Vector{MonthlyRecord})::Vector{MonthlyRecord}Returns a 12-month climatology taken from the final year of records.
GREBClimate.circulation! — Method
circulation!(X_in, h_scl, dX_out, fields::ClimateFields, ws::CirculationWorkspace, timestate, cfg::PhysicsConfig)Sub-steps X_in through ntime iterations of diffusion!, advection!, and convergence! (each gated by the relevant cfg.log_* switch), writing the total change into dX_out. The sub-step loop is a genuine sequential recurrence and is not parallelized.
GREBClimate.compute_annual_ice_climatology — Method
compute_annual_ice_climatology(ctrl_output::Vector{MonthlyRecord})Returns ctrl_output's ice field from the final year, as an (xdim, ydim, 12) array.
GREBClimate.convergence! — Method
convergence!(T1, fields::ClimateFields, timestate, ws::CirculationWorkspace)Moisture flux convergence from T1 (specific humidity, [kg/kg]) and the current fields.omegaclim (vertical velocity), writing the tendency into ws.dX_conv. Implements Eq. 18 from Stassen et al. (2019).
GREBClimate.create_experiment_config — Method
create_experiment_config(experiment::Symbol; co2_path="", orbital_index=0,
earth_sun_distance_pct=0.0, log_clouds_dmc=nothing, log_ocean_dmc=nothing,
log_atmos_dmc=nothing, log_co2_dmc=nothing, log_hydro_dmc=nothing,
log_qflux_dmc=nothing, log_topo_drsp=nothing, log_clouds_drsp=nothing,
log_humid_drsp=nothing, log_ocean_drsp=nothing, log_hydro_drsp=nothing,
log_ice=nothing, log_hdif=nothing, log_hadv=nothing, log_vdif=nothing,
log_vadv=nothing) -> PhysicsConfigCreate a pre-configured PhysicsConfig for any experiment the model dispatches on. Errors on an unknown symbol, listing the valid ones.
The 16 log_* keywords are used only by :decon_mean_climate/:decon_2xco2; passing one for any other experiment warns and is ignored, rather than being silently dropped. co2_path applies only to :custom_co2, orbital_index to the paleo/orbital experiments, and earth_sun_distance_pct to :earth_sun_distance.
Only :constant_topo, :co2_double, :co2_quadruple, :paleo_231kyr and the three forced-boundary experiments carry a static override; every other entry is experiment = sym alone, because forcing sets the scenario CO₂ per timestep and co2_concentration seeds the control run.
Experiments
:full_model- All processes active (default):constant_topo- Constant topography (logtopodrsp = false), 2×CO₂ scenario:co2_double/:co2_quadruple/:co2_10x/:co2_half/:co2_zero- CO₂ scaling:co2_sine_wave/:co2_step- time-varying CO₂:a1b_scenario- A1B CO₂ ramp (control baseline 280 ppm):solar_plus27- +27 W/m² solar constant:solar_cycle_11yr- 11-year solar cycle:paleo_231kyr- Paleoclimate (200 ppm CO₂):paleo_solar_modern_co2/:modern_solar_paleo_co2- crossed paleo/modern forcing:obliquity/:eccentricity- orbital forcing,orbital_indexselects the table row:earth_sun_distance- solar constant scaled byearth_sun_distance_pct:elnino/:lanina- ERA-Interim ENSO conditions:rcp26/:rcp45/:rcp60/:rcp85- IPCC RCP climate change scenarios:ssp119/:ssp126/:ssp245/:ssp460/:ssp585- IPCC SSP scenarios:historical_co2- Observed CO₂ 1850-2017 (year starts at 1850, not 1950):custom_co2- user-supplied CO₂ trajectory,co2_pathkeyword gives the "year CO2" text file path (seeload_custom_co2_scenario):sst_plus1- ocean surface warmed 1 K, CO₂ held at control:regional_co2_nh/:regional_co2_sh/:regional_co2_tropics/:regional_co2_extratropics- 2×CO₂ over a latitude band (static mask, set byinit_model!):regional_co2_ocean/:regional_co2_land_ice- 2×CO₂ over ocean or land/ice (mask derived from the control run's ice cover, seeapply_dynamic_co2_mask!):regional_co2_winter/:regional_co2_summer- 2×CO₂ in one boreal season:decon_mean_climate- deconstruct-mean-state experiment:decon_2xco2- deconstruct-2×CO₂-response experiment
Examples
julia> cfg = create_experiment_config(:co2_double);
julia> cfg.experiment, cfg.co2_concentration
(:co2_double, 680.0f0)
julia> create_experiment_config(:constant_topo).log_topo_drsp
falseGREBClimate.deep_ocean! — Method
deep_ocean!(Ts, To, fields::ClimateFields, timestate, cfg::PhysicsConfig, ws::CirculationWorkspace)Computes surface/deep-ocean coupling tendencies (dT_ocean, dTo) from mixed-layer-depth entrainment/detrainment and turbulent mixing, active only where the point is ocean and above the sea-ice threshold. Returns zeros if cfg.log_ocean_dmc/cfg.log_ocean_drsp disable ocean coupling.
GREBClimate.diagnostics! — Method
diagnostics!(it, year, CO2, surf::SurfaceState, tend, fields, state, timestate)Accumulates the current timestep into state's annual-mean buffers; at the last timestep of the year, averages them, prints the annual summary line (global mean + two sample points), and resets the accumulators for the next year. tend is the NamedTuple tendencies! returns.
GREBClimate.diffusion! — Method
diffusion!(T1, h_scl, fields::ClimateFields, ws::CirculationWorkspace, timestate)Meridional + zonal diffusion of T1 (temperature or humidity), writing the tendency into ws.dX_diff. h_scl (z_air or z_vapor) selects the topographic weighting field.
GREBClimate.forcing — Method
forcing(it, year, cfg::PhysicsConfig, fields::ClimateFields, icmn_ctrl; nstep_yr=nstep_yr)Returns (CO2, sw_solar_forcing) for the current timestep, computed according to cfg.experiment. Pure - the regional_co2_* masks are built once per run by apply_dynamic_co2_mask!, not here. :full_model short-circuits before the experiment dispatch chain. The :rcp26/:rcp45/:rcp60/ :custom_co2/:ssp*/:historical_co2 experiments look year up in cfg.co2_scenario.
GREBClimate.greb_data_dir — Function
greb_data_dir(path = nothing; allow_download = true) -> String or nothingReturn the directory holding the JLD2 input dataset, resolving in this order:
path, if given and non-empty.ENV["GREB_DATA"], if set.greb_input_data/next to the package, if it exists.- An already-downloaded
GREB-input-dataDataDep, if its cache is present. - The
GREB-input-dataDataDep - downloading it on first use, after asking.
Pass allow_download = false to stop after step 4 and return nothing when no dataset is available locally. Test suites and benchmarks use this so that running them can never pull 353 MB over the network as a side effect.
The result is a plain path, suitable for load_greb_jld2! and greb_model!'s jld2_dir:
dir = greb_data_dir()
fields = load_greb_jld2!(dir; dataset = :ncep)
result = greb_model!(RunSpec(), cfg; jld2_dir = dir, fields = fields)GREBClimate.greb_model! — Method
greb_model!(run::RunSpec, cfg::PhysicsConfig; jld2_dir="", fields=ClimateFields(),
allow_uninitialized=false)Run a GREB flux-correction spin-up (run.flux years), control run (run.ctrl years), and scenario run (run.scnr years) for cfg.
fields holds the loaded climatology/grid/flux-correction state (see ClimateFields, built by load_greb_jld2!). Pass the same fields instance across multiple calls to reuse already-loaded climatology instead of reloading it - that's the only case where co2_part/sw_solar mutations from one run could otherwise leak into the next; this function resets/restores them per-run regardless.
GREBClimate.hydro! — Method
hydro!(Ts, q, fields::ClimateFields, timestate, cfg::PhysicsConfig, ws::CirculationWorkspace)Computes latent heat flux and evaporation/rain tendencies. cfg.log_eva (-1/0/1/2) selects the wind-gust/coefficient parameterization used for evaporation; cfg.log_rain (via cfg.c_q/c_rq/c_omega/c_omegastd, set by set_hydrology_parameters!) controls the rain regression. Returns (Q_lat, Q_lat_air, dq_eva, dq_rain).
GREBClimate.init_model! — Method
init_model!(cfg::PhysicsConfig, fields::ClimateFields)One-time per-run setup: derives cfg's hydrology parameters, resets the regional-CO₂ mask, applies CO₂-response climatology overrides (log_clouds_drsp/log_humid_drsp/log_ocean_drsp), and computes the control-run initial state. Returns (Ts_ini, Ta_ini, To_ini, q_ini, CO2_ctrl).
GREBClimate.load_cc_anomaly_jld2! — Method
load_cc_anomaly_jld2!(jld2_dir::String, fields::ClimateFields, cfg::PhysicsConfig)Loads the CMIP5 RCP8.5 ensemble-mean climate-change anomaly fields into fields.Tclim_anom_cc/uclim_anom_cc/vclim_anom_cc/omegaclim_anom_cc/ wsclim_anom_cc, gated per-field by cfg.log_tsurf_ext/log_hwind_ext/ log_omega_ext. Errors on a missing file rather than defaulting to zero, since this data is the :rcp85 experiment's forcing.
GREBClimate.load_co2_scenario_jld2 — Method
load_co2_scenario_jld2(jld2_dir::String, scenario::Symbol) -> Dict{Int,Float32}Loads a year => CO2 (ppm-equivalent) lookup table for an IPCC scenario (e.g. :ssp585, :rcp85) from the combined scenario/ipcc_scenarios.jld2.
GREBClimate.load_custom_co2_scenario — Method
load_custom_co2_scenario(path::String) -> Dict{Int,Float32}Loads a year => CO2 lookup table for the :custom_co2 experiment from a plain-text file, one year CO2 pair per line. Blank lines and lines starting with # are skipped.
GREBClimate.load_enso_anomaly_jld2! — Method
load_enso_anomaly_jld2!(jld2_dir::String, fields::ClimateFields, cfg::PhysicsConfig, which::Symbol)Loads the ERA-Interim composite-mean El Niño (which=:elnino) or La Niña (:lanina) anomaly fields into fields.*_anom_enso, gated the same way as load_cc_anomaly_jld2!.
GREBClimate.load_flux_corrections_jld2! — Method
Load flux corrections from the combined climatology/flux_corrections.jld2 into fields (zeros per-field if the file or an individual key is missing).
GREBClimate.load_greb_jld2! — Method
load_greb_jld2!(jld2_dir::String; dataset::Symbol=:ncep)Load all GREB input data from JLD2 formatted files, returning a fresh ClimateFields. dataset (:ncep/:era) selects which climatology files to read; this is independent of PhysicsConfig.log_clim, which only selects hydrology regression coefficients in set_hydrology_parameters!.
GREBClimate.load_solar_forcing_jld2 — Function
load_solar_forcing_jld2(jld2_dir::String, forcing_type::Symbol, index::Int=0)Loads an alternate solar-forcing table for paleo/orbital experiments. forcing_type is :paleo, :eccentricity, or :obliquity; for the latter two, index selects the matching row by coordinate value. Used by greb_model! to temporarily swap fields.sw_solar for these experiments.
GREBClimate.output! — Method
output!(it, irec, mon, surf::SurfaceState, tend, ws, output_buf, acc, timestate)Accumulates the current timestep into acc; on the last timestep of mon, pushes a monthly-mean MonthlyRecord onto output_buf, resets acc, and advances to the next month. Returns (mon, irec). tend is the NamedTuple tendencies! returns; ws.precip_out/evap_out/ qcrcl_out hold this step's converted precipitation/evaporation/moisture- circulation output.
GREBClimate.qflux_correction! — Method
qflux_correction!(CO2_ctrl, Ts, Ta, q, To, fields, state, timestate, cfg, ws, time_flux; ws_a=ws, ws_q=ws)Runs time_flux years of tendencies! to derive the ocean/atmosphere flux corrections (fields.TF_correct/qF_correct/ToF_correct) that make the control climate match observed climatology. Mutates Ts/Ta/q/To in place as it integrates. ws_a/ws_q are forwarded to tendencies!
GREBClimate.read_jld2 — Method
read_jld2(filepath::String)Read a .jld2 field file written by tools/convert_greb_to_jld2.jl.
Returns
- named tuple
(data, dim_names, coords, ctl)where:data: Array{Float32} with shape as storeddim_names: Vector{String} of dimension names (e.g., ["lon", "lat", "time"])coords:Dict{Int,Vector{Float64}}of physical coordinate values per dimension index, ornothingif the file has nonectl: raw GrADS.ctlmetadata text, ornothingif the file has none
GREBClimate.refresh_ghosts! — Method
Refresh the wrap-around ghost rows of a (xghost, ydim) buffer.
GREBClimate.refresh_ghosts! — Method
Refresh the wrap-around ghost entries of a length-xghost vector.
GREBClimate.register_greb_datadep — Method
register_greb_datadep()Register the dataset with DataDeps. Called from GREBClimate.__init__; registration itself is cheap and downloads nothing.
GREBClimate.seaice! — Method
seaice!(Ts0, fields::ClimateFields, timestate, cfg::PhysicsConfig)Updates fields.cap_surf (surface heat capacity) for ocean points based on Ts0-derived ice fraction, blending land/open-ocean/ice capacities. No-op if cfg.log_ocean_dmc is false; skips the ice-albedo blend if cfg.log_ice is false.
GREBClimate.set_hydrology_parameters! — Method
set_hydrology_parameters!(cfg::PhysicsConfig)Initialize precipitation parameters c_q, c_rq, c_omega, c_omegastd based on cfg.log_rain and cfg.log_clim settings.
GREBClimate.tendencies! — Method
tendencies!(CO2, Ts, Ta, To, q, fields, state, ws, timestate, cfg; ws_a=ws, ws_q=ws)Runs one timestep's physics pipeline - SWradiation! → LWradiation! → sensible heat → hydro! → circulation! (temperature, then humidity) → deep_ocean! - and returns a named tuple of every intermediate flux/tendency needed by diagnostics! and the caller's own state update.
The two circulation! calls are independent of each other and of every other stage (each reads only pre-timestep state and writes disjoint buffers), so when the caller supplies distinct ws_a/ws_q workspaces and Threads.nthreads() > 1, they run concurrently via Threads.@spawn while the remaining stages run on ws. With the default ws_a=ws_q=ws
GREBClimate.time_loop! — Method
time_loop!(it, year, CO2, mon, irec, Ts, Ta, q, To, output_buf, fields, state, ws, acc, timestate, cfg; ws_a=ws, ws_q=ws)One full model timestep: computes tendencies!, integrates Ts/Ta/To/q forward with flux corrections applied, runs seaice!, then dispatches to output! and diagnostics!. Returns (mon, irec). ws_a/ws_q are forwarded to tendencies! - see its docstring for the opt-in threading they enable.
GREBClimate.to_ghosted! — Method
Copy an (xdim, ydim) field into the ghosted buffer P and fill its ghosts.