Models API
The Models module contains the runtime stepper — TransportModel, DrivenSimulation, the IC pipeline, and the recipe builders that turn a TOML config into a fully-wired runtime object.
AtmosTransport.Models.DrivenSimulation Type
DrivenSimulationLow-level window-driven runtime for custom driver/model wiring.
Most TOML-based runs should go through run_driven_simulation, which builds and validates this object for you. Construct DrivenSimulation directly only when you need a custom met driver, callback loop, or model assembly.
A DrivenSimulation keeps transport-window timing and forcing in the driver, while the model retains ownership of prognostic tracer and air-mass state. The runtime interpolates forcing within each met window and advances the model with the same step!(model, Δt) entry point used by the fixed-flux smoke harness.
For experienced users, the constructor is meant to be assembled from the same pieces used by run_driven_simulation: a met driver, a basis-compatible state, empty flux storage owned by the model, and a runtime physics recipe. A minimal LL/RG manual setup looks like this:
using TOML, AtmosTransport
using AtmosTransport.MetDrivers: air_mass_basis, driver_grid, flux_kind
# First run examples/generate_synthetic_quickstart.jl from the terminal.
cfg = TOML.parsefile("config/examples/minimal_template.toml")
paths = expand_binary_paths(cfg["input"])
FT = Float64
driver = TransportBinaryDriver(first(paths); FT = FT, arch = CPU())
recipe = build_runtime_physics_recipe(cfg, driver, FT)
validate_runtime_physics_recipe(recipe, driver)
grid = driver_grid(driver)
window1 = load_transport_window(driver, 1)
Basis = air_mass_basis(driver) === :dry ? DryBasis : MoistBasis
air = copy(window1.air_mass)
vmr = build_initial_mixing_ratio(
air, grid, Dict("kind" => "uniform", "background" => 400e-6);
surface_pressure = window1.surface_pressure,
)
co2 = pack_initial_tracer_mass(grid, air, vmr; mass_basis = Basis())
state = CellState(Basis, air; CO2 = co2)
fluxes = allocate_face_fluxes(grid.horizontal, nlevels(grid);
FT = FT, basis = Basis)
model = TransportModel(state, fluxes, grid, recipe.advection;
diffusion = recipe.diffusion,
convection = recipe.convection)
sim = DrivenSimulation(model, driver;
stop_window = min(total_windows(driver), 24),
chemistry = recipe.chemistry)
run_window!(sim)The full runner adds the practical edges around this skeleton: resolving many daily binaries, GPU adaptation, surface-flux source construction, snapshot output, progress reporting, and capability checks against every file.
SurfaceFluxSource lives with the surface-flux operator in src/Operators/SurfaceFlux/.
AtmosTransport.Models.DrivenSimulation Method
DrivenSimulation(model, driver; kwargs...)Construct a window-driven src runtime.
Keyword arguments:
start_window=1stop_window=total_windows(driver)initialize_air_mass=trueuse_midpoint_forcing=trueinterpolate_fluxes_within_window=nothing(derive from driver)air_mass_reset_mode=:preserve_tracer_mass— one of:none,:preserve_vmr, or:preserve_tracer_mass. When non-:none, each newly loaded window replaces prognostic air mass using the selected tracer invariant. For binary-scheduled runs, the same endpoint reset is applied before the once-per-window convection/chemistry block so physics sees the binary's authoritative window-end mass.surface_sources=()chemistry=NoChemistry()— applied after advection + surface sources each stepcallbacks=NamedTuple()start_time=0— simulation clock origin [s]. Multi-binary runners MUST pass the accumulated run time here when rebuilding the sim per binary:sim.timefeedscurrent_time(meteo), which time-varying surface-flux sources use to select their emission slice (seconds since the RUN start, not the binary start). Restarting the clock at 0 each day silently replays day-1 fluxes — the December-2021 co2_natural +1 Pg/month surplus (plan 45 Stage-4 A/B experiment attributed the leak to exactly this).
AtmosTransport.Models.Simulation Type
SimulationLow-level fixed-step harness for custom in-memory experiments.
Most users should call run_driven_simulation with a run config. Use Simulation only when you already constructed a TransportModel and want to drive it with a custom time loop.
AtmosTransport.Models.TransportModel Type
TransportModel(state, fluxes, grid, advection; kwargs...)Minimal Oceanigans-style model object for standalone src transport runs.
Carries advection, chemistry, vertical diffusion, surface emissions, and convection operators. The step composition is: transport_block(dt) → convection_block(dt) → chemistry_block(dt)
where transport_block runs the full palindrome with diffusion and emissions at the center:
X → Y → Z → V(dt/2) → S(dt) → V(dt/2) → Z → Y → X (emissions active)
X → Y → Z → S(dt) → V(dt) → Z → Y → X (diffusive boundary coupling)
X → Y → Z → V(dt) → Z → Y → X (no emissions)step!(model, dt) executes the full runtime composition: transport block → convection block → chemistry block.
Defaults chemistry = NoChemistry(), diffusion = NoDiffusion(), emissions = NoSurfaceFlux(), and convection = NoConvection() make the inactive operator slots compile to no-op dispatches.
Convection fields
convection :: ConvT— operator type, defaults toNoConvection(). Concrete subtypes areCMFMCConvectionandTM5Convection.NoConvectionis a compile-time dead branch instep!.convection_forcing :: CF— per-step forcing container. Defaults toConvectionForcing()(all-nothing placeholder).DrivenSimulationconstruction allocates real buffers viaallocate_convection_forcing_like;_refresh_forcing!populates them fromsim.window.convectioneach substep.
Helpers with_convection(model, op) and with_convection_forcing(model, forcing) parallel with_chemistry / with_diffusion / with_emissions.
AtmosTransport.Models.advection_spec Method
advection_spec(section) -> AbstractAdvectionSpecParse an [advection] section into a typed spec. ppm_order is only meaningful for scheme = "linrood"; pairing it with scheme = "ppm" is rejected (the split PPM path takes no order knob), matching the old builder.
AtmosTransport.Models.build_runtime_chemistry Method
build_runtime_chemistry(cfg, ::Type{FT}) -> AbstractChemistryOperatorRead the optional [chemistry] TOML section and produce the corresponding chemistry operator.
Supported kind values:
"none"(default) —NoChemistry()."decay"—ExponentialDecay(FT; ...). Half-lives are read from thehalf_lives_secondstable:[chemistry] kind = "decay" [chemistry.half_lives_seconds] rn222 = 330350.4 # 3.8235 daysThe keyword name must match the corresponding
[tracers.<name>]symbol that the run is carrying (case-insensitive — the builder symbolizes the key as-is andExponentialDecay.apply!resolves it againststate.tracer_namesat call time).
Thin wrapper: parse the [chemistry] section into a typed AbstractChemistrySpec once (validated), then materialize at run precision FT. Spec types + parser live in RuntimePhysicsSpecs.jl.
AtmosTransport.Models.build_runtime_physics_recipe Method
build_runtime_physics_recipe(cfg, context, FT; halo_width=nothing)Parse typed advection, diffusion, convection, and chemistry specifications from cfg, materialize them for context and floating-point type FT, then run the complete runtime compatibility validation.
sourceAtmosTransport.Models.chemistry_spec Method
chemistry_spec(section) -> AbstractChemistrySpecParse a [chemistry] section into a typed spec. kind = "decay" with an empty (or absent) half_lives_seconds table reduces to NoChemistrySpec — matching the old builder (an inert decay scheme is just no chemistry). Each half-life is validated positive at parse time (the old builder silently produced an Inf/negative decay rate for a non-positive value).
AtmosTransport.Models.convection_chemistry_step! Method
convection_chemistry_step!(model::TransportModel, dt; meteo = nothing)Advance the non-transport physics blocks once: convection block → chemistry block.
sourceAtmosTransport.Models.convection_spec Method
convection_spec(section) -> AbstractConvectionSpecParse a [convection] TOML section into a typed spec, validating at the boundary.
INTENTIONAL behavior change vs the old builder: the collaborative-LU knobs lmax_conv/n_merge only take effect when use_collab_lu = true (they steer the workgroup-collaborative kernel; the legacy per-thread path ignores them). Setting them without use_collab_lu used to be a silent no-op; it is now a hard error.
AtmosTransport.Models.diffusion_spec Method
diffusion_spec(section) -> AbstractDiffusionSpecParse a [diffusion] section into a typed spec, validating at the boundary. An empty/absent section or kind = "none" is explicit "no diffusion". The legacy type = "..." schema is rejected (it used to silently fall through to NoDiffusion, hiding configs that expected diffusion to run); a present section with no kind is rejected too.
AtmosTransport.Models.run! Method
run!(simulation)Advance a Simulation or DrivenSimulation until its configured stop condition. Returns the mutated simulation.
sourceAtmosTransport.Models.run_window! Method
run_window!(sim::DrivenSimulation)Advance exactly the current meteorological window and return sim. If sim is positioned at a completed non-final window, the next window is loaded first.
sourceAtmosTransport.Models.step! Method
step!(model::TransportModel, dt; meteo = nothing)Advance model.state by one full runtime step: transport block (advection with vertical diffusion at the palindrome center, surface emissions wrapped by the two V half-steps when active) → convection block → chemistry block.
With defaults diffusion = NoDiffusion(), emissions = NoSurfaceFlux(), chemistry = NoChemistry(), convection = NoConvection(), every live component is a dead branch and the call is bit-exact equivalent to the advection-only path.
meteo is optional and defaults to nothing; pass a real meteorology object (AbstractMetDriver) or a DrivenSimulation to thread current_time(meteo) through operators that consume time-varying fields.
AtmosTransport.Models.transport_step! Method
transport_step!(model::TransportModel, dt; meteo = nothing)Advance model.state by one transport step: advection with vertical diffusion at the palindrome center and surface emissions. The diffusion operator's coupling policy selects either V(dt/2) -> S(dt) -> V(dt/2) or S(dt) -> V(dt) when both diffusion and a surface source are active.
Binary-scheduled driven runs use this block at the per-window advection substep cadence stored in the transport binary. Convection and chemistry are separate physics blocks and can run at the met-window cadence via convection_chemistry_step!.
AtmosTransport.Models.validate_runtime_physics_recipe Method
validate_runtime_physics_recipe(recipe, context; halo_width=nothing)Validate topology support, binary capabilities, and halo requirements for a materialized RuntimePhysicsRecipe. Returns recipe or throws ArgumentError before model allocation.
sourceAtmosTransport.Models.with_chemistry Method
with_chemistry(model::TransportModel, chemistry)Return a copy of model with its chemistry operator replaced. All other fields share storage with the original. Chemistry is installed into the model rather than held at the sim level, so this helper is primarily useful for tests that want to swap chemistry on a constructed model.
AtmosTransport.Models.with_convection Method
with_convection(model::TransportModel, convection)Return a copy of model with its convection operator replaced. All other fields — including convection_forcing — share storage with the original.
Note: with_convection does NOT allocate convection-forcing buffers. The model-side ConvectionForcing() placeholder stays as-is. DrivenSimulation construction is responsible for allocating real buffers via allocate_convection_forcing_like after the first window loads. For tests that bypass the sim layer, use with_convection_forcing(model, forcing) to inject allocated buffers directly. The model workspace is re-wrapped as needed so concrete operators can carry their own scratch storage without disturbing the advection workspace.
AtmosTransport.Models.with_convection_forcing Method
with_convection_forcing(model::TransportModel, forcing::ConvectionForcing)Return a copy of model with its per-step convection-forcing container replaced. All other fields — including the convection operator — share storage with the original.
Used by DrivenSimulation construction to install the allocated forcing buffers after the first window loads. Also useful for tests that inject forcing directly without going through the sim's _refresh_forcing! path.
AtmosTransport.Models.with_diffusion Method
with_diffusion(model::TransportModel, diffusion)Return a copy of model with its diffusion operator replaced. All other fields share storage with the original. Parallel to with_chemistry; useful for installing a diffusion operator into a model that was constructed with the default NoDiffusion().
AtmosTransport.Models.with_emissions Method
with_emissions(model::TransportModel, emissions)Return a copy of model with its surface-emissions operator replaced. All other fields share storage with the original. Parallel to with_chemistry and with_diffusion; used by DrivenSimulation to install the sim-level surface_sources tuple as a SurfaceFluxOperator inside the wrapped model, so the palindrome's S slot runs at the right place in the transport block without sim-level post-step hacks.
AtmosTransport.Models.InitialConditionIO Module
InitialConditionIOSingle owner of initial-condition I/O, vertical remap, and topology-dispatched VMR builders for the unified runtime.
Public API (exported via Models → AtmosTransport)
build_initial_mixing_ratio— topology-dispatched builder returning dry VMR on interior cells. Acceptskind = uniform | latitude_step | gaussian_blob | file | netcdf | file_field | catrine_co2for LL/RG meshes. CS supportsuniform | latitude_step | gaussian_blob | file | netcdf | file_field | catrine_co2.pack_initial_tracer_mass— basis-aware VMR → conservative model storage conversion. Dispatches onmass_basis::AbstractMassBasis:DryBasis(default per CLAUDE.md invariant 14):rm = vmr .* air_mass.MoistBasis:rm = vmr .* air_mass .* (1 .- qv)per CLAUDE.md invariant 9;qvmust be supplied.
FileInitialConditionSource— container for a loaded IC NetCDF (3D VMR + hybrid coefficients + surface pressure).
Contents
LL/RG and CS
build_initial_mixing_ratioforuniform | file | catrine_co2 | netcdf | file_field.Basis-aware
pack_initial_tracer_mass(DryBasis + MoistBasis); CS output is halo-padded with the halo zeroed._build_source_latlon_meshhelper for LL→CS conservative regridding.Surface-flux NetCDF loader (13 helpers +
FileSurfaceFluxFieldstruct) and LL/RGbuild_surface_flux_sourcemethods; CSbuild_surface_flux_sourceconservatively LL→CS-regrids the flux (the regridder'sdst_areas× regridded density already yields kg/s per cell) and unpacks toNTuple{6, Matrix{FT}}— satisfying the per-cell kg/s contract atsrc/Operators/SurfaceFlux/sources.jl:12.
Private helpers (underscore-prefixed) stay unexported and are accessed by callers (including the canonical driven runtime) via AtmosTransport.Models.InitialConditionIO.<name> if needed.
AtmosTransport.Models.InitialConditionIO.FileInitialConditionSource Type
FileInitialConditionSource{FT}Container for a file-based initial condition (e.g. Catrine startCO2).
Fields
raw— 3D mixing ratio field(nlon_src, nlat_src, nlevel_src). Level ordering follows the source file (Catrine: k=1 is SURFACE, k=end is TOA — verify viaap[1]+bp[1]*ps ≈ ps).lon,lat— source coordinate vectors [degrees]. May be in [-180,180) or [0,360); the bilinear sampler wraps to [0,360) internally viawrapped_longitude_360.ap,bp— hybrid half-level coefficients(nlevel_src + 1):p_half[k] = ap[k] + bp[k] × ps_src. Units:ap[Pa],bp[dimensionless].psurf— surface pressure(nlon_src, nlat_src)[Pa].needs_vinterp—trueif source levels ≠ target levels (triggers log-pressure vertical interpolation in_interpolate_log_pressure_profile!).
AtmosTransport.Models.InitialConditionIO.FileSurfaceFluxField Type
FileSurfaceFluxField{FT}2-D flux density (Nx_src, Ny_src) loaded from a NetCDF emission file. Units are kg/m²/s after _load_file_surface_flux_field has normalised the native units. native_total_mass_rate is the pre-regrid global integral, preserved for the bilinear path's renormalisation (the conservative path does not need it).
AtmosTransport.Models.InitialConditionIO.TimeVaryingFileSurfaceFluxField Type
TimeVaryingFileSurfaceFluxField{FT}A stack of 2-D flux-density slices (Nx_src, Ny_src, ntime) loaded from a NetCDF emission file, keeping every time slice (no monthly averaging). Units are kg/m²/s after _load_timevarying_surface_flux_field has normalised the native units, identically per slice. times_sec holds the slice times in seconds since the run reference_time, ascending.
AtmosTransport.Models.InitialConditionIO.build_initial_mixing_ratio Method
build_initial_mixing_ratio(air_mass, mesh, cfg)
build_initial_mixing_ratio(air_mass, grid::AtmosGrid, cfg; surface_pressure=nothing)Construct the initial dry-air volume mixing ratio described by cfg on the horizontal topology and vertical layout of air_mass.
Bare lat-lon and reduced-Gaussian meshes support the analytic uniform, latitude_step, and gaussian_blob modes; bl_enhanced is lat-lon only. Passing an AtmosGrid additionally enables file-backed modes (file, netcdf, file_field, and catrine_co2) with topology-aware horizontal mapping and log-pressure vertical interpolation. Cubed-sphere construction requires an AtmosGrid and also supports pressure_layer and cs_native. File-backed and pressure-layer construction require the transport window's surface_pressure where indicated by the selected mode.
Returns an array shaped like air_mass for lat-lon and reduced-Gaussian grids, or an NTuple{6} of interior (Nc, Nc, Nz) arrays for cubed-sphere grids.
AtmosTransport.Models.InitialConditionIO.build_surface_flux_source Method
build_surface_flux_source(grid::AtmosGrid{<:CubedSphereMesh},
tracer_name, cfg, ::Type{FT})CS surface-flux builder. Conservatively LL→CS regrids the 2-D flux density (kg/m²/s) onto the 6 CS panel cell centres, multiplies by each panel's cell area to yield per-cell kg species/s, then converts that physical rate to the model storage basis. Returns a SurfaceFluxSource whose cell_mass_rate is an NTuple{6, Matrix{FT}} of interior-only (Nc, Nc) panels.
cfg must set kind (non-none); any of the file-based surface-flux kinds _load_file_surface_flux_field understands work (gridfed_fossil_co2 or user-supplied file + variable). Conservative regridding is enforced — CS bilinear is not supported.
If cfg["time_varying"] = true and the kind supports a 3-D (lon,lat,time) series (currently :lmdz_co2), the builder keeps every time slice, builds the LL→CS regridder ONCE, applies it per slice, and returns a TimeVaryingSurfaceFluxSource whose cell_mass_rate_series is an NTuple{6} of (Nc, Nc, ntime) panels plus a times vector (seconds since reference_time). The default (time_varying absent/false) path is byte-identical to before.
AtmosTransport.Models.InitialConditionIO.build_surface_flux_sources Method
build_surface_flux_sources(grid, tracer_specs, ::Type{FT}; reference_time=nothing)Build surface-flux source instances for every tracer spec that requests one. Returns a tuple (possibly empty) suitable for the surface_sources = (…,) kwarg on DrivenSimulation.
reference_time (the run start DateTime) is threaded to each per-tracer builder so the time-varying CS path can align its slice times to the simulation clock. It is ignored by static sources.
AtmosTransport.Models.InitialConditionIO.pack_initial_tracer_mass Method
pack_initial_tracer_mass(grid, air_mass, vmr_dry; mass_basis::AbstractMassBasis,
qv = nothing)Convert dry volume mixing ratio vmr_dry to conservative model storage matching the binary's mass-basis contract. On DryBasis that storage is vmr_dry × dry_air_mass; it is not physical kg species. Returns an array of the same shape as air_mass.
Dispatch
mass_basis::DryBasis—air_massism_dryper CLAUDE.md invariant 14. Result:vmr_dry .* air_mass.qvis ignored.mass_basis::MoistBasis—air_massism_moistper CLAUDE.md invariant 9. Result:vmr_dry .* air_mass .* (1 .- qv).qvmust be supplied from the first transport window; missingqverrors.
CS dispatch handles per-panel halo packing.
Arguments
grid—AtmosGrid{<:LatLonMesh}orAtmosGrid{<:ReducedGaussianMesh}(CS added in 1c).air_mass— storage-shaped air mass from the transport window. Shape matchesvmr_dry.vmr_dry— dry volume mixing ratio, same shape asair_mass.mass_basis—DryBasis()orMoistBasis().qv— specific humidity, same shape asair_mass; required iffmass_basis isa MoistBasis.
AtmosTransport.Models.BinaryPathExpander Module
BinaryPathExpanderExpand a [input] TOML block into a sorted list of transport-binary file paths. Supports both an explicit-list shape and a folder + date-range shape with continuity verification. Keeps the runtime file-window contract unchanged; the CLI simply receives a longer or shorter Vector{String}.
Accepted TOML shapes
# Shape A (current, preserved): explicit list
[input]
binary_paths = ["...a.bin", "...b.bin"]
# Shape B (new): folder + inclusive date range
[input]
folder = "~/data/.../cs_c48/.../"
start_date = "2021-12-01"
end_date = "2021-12-10"
file_pattern = "era5_transport_{YYYYMMDD}_merged1000Pa_float32.bin" # optionalShapes A and B are mutually exclusive.
Folder scanning
When folder is supplied:
readdir(folder)→ candidate filenames.Each filename is parsed for an 8-digit
YYYYMMDDtoken. Iffile_patternis supplied, the{YYYYMMDD}placeholder marks where the date lives, and the surrounding text is matched literally (as a regex). Withoutfile_pattern, any\d{8}run anywhere in the filename is used.Files parseable as dates within
[start_date, end_date]are kept; files outside the range are silently dropped; files that don't match the pattern error out.The resulting sorted list is verified for continuity: every date in the closed interval must be present. Missing days list in the error message.
Returns
Vector{String} of absolute paths, sorted chronologically by parsed date.
AtmosTransport.Models.BinaryPathExpander.expand_binary_paths Method
expand_binary_paths(input_cfg::AbstractDict) -> Vector{String}See module docstring for the accepted TOML shapes. Throws ArgumentError on mutual exclusion, missing folder, date parse failure, or gaps in the date range.
AtmosTransport.Models.InputStaging.InputStager Type
InputStagerRolling local-disk stager for the daily transport binary list. Construct from the resolved NAS binary_paths and the [input.staging] config sub-table; call staged_path_for! at each day's driver-open site and cleanup_staging! at run end.
All mutable bookkeeping (staged, tasks, failed) is touched only by the main loop thread — background tasks are pure (copy + return the path or throw), so there is no shared-state race.
AtmosTransport.Models.InputStaging.InputStager Method
InputStager(binary_paths, staging_cfg)Parse the [input.staging] sub-table and build the stager. Keys (all optional):
enabled: Bool (defaultfalse⇒ no staging, NAS paths used)dir: String (REQUIRED when enabled) — local NVMe directorylookahead_days: Int (default2)keep_behind_days: Int (default0)cleanup_on_exit: Bool (defaulttrue)
AtmosTransport.Models.InputStaging.cleanup_staging! Method
cleanup_staging!(mgr)Wait for any in-flight copies and remove all remaining staged files (when cleanup_on_exit). Safe to call unconditionally at run end.
AtmosTransport.Models.InputStaging.staged_path_for! Method
staged_path_for!(mgr, idx) -> StringReturn the path the day-idx driver should open. With staging enabled this ensures day idx is on local NVMe (blocking only if its copy is still in flight), kicks off async copies for the look-ahead window, and evicts processed days. Falls back to the NAS path if the copy failed. With staging disabled it returns the original NAS path unchanged.
AtmosTransport.Models.DrivenRunner Module
DrivenRunnerLibrary-level entry point for the driven transport runtime.
The canonical CLI, scripts/run_transport.jl, is a thin wrapper over run_driven_simulation(cfg). The library function handles LL/RG and CS runtime flows with dispatch driven by the first binary's header (inspect_binary(first_path).grid_type). Historical runner names live under scripts/deprecated/ only for reference.
Ownership boundary
Binary header (
grid_type,mass_basis,payload_sections, panel convention) — authoritative for topology and capability. Accessed here viabinary_capabilities(driver.reader)andair_mass_basis(driver).TOML
[input]— either an explicitbinary_paths = [...]list (Shape A) or afolder + start_date + end_date (+ file_pattern)block (Shape B). Both are resolved to a sortedVector{String}byexpand_binary_paths.TOML physics (
[advection]/[diffusion]/[convection]) — validated against binary capabilities byvalidate_runtime_physics_recipe/build_runtime_physics_recipebefore the loop.TOML
[tracers.*]— tracer specs consumed viabuild_initial_mixing_ratio+pack_initial_tracer_mass(basis-aware perfeedback_vmr_to_mass_basis_aware) andbuild_surface_flux_sources.
Where the physics actually runs
DrivenRunner is the orchestration layer, not the kernel layer. It opens transport binaries, builds initial state, chooses output cadence, and installs the TOML-selected operators on a TransportModel. The live physics call chain is:
build_runtime_physics_recipereads[advection],[diffusion],[convection],[chemistry], and tracer surface-flux settings and returns the operator objects._make_structured_modelor the CS model constructor installs those operators onTransportModel(state, fluxes, grid, recipe.advection; ...).DrivenSimulation(model, driver; ...)loads the current met window and wraps chemistry and surface sources into the model withwith_chemistryandwith_emissions.The runtime loop below calls
run_window!(sim)for LL/RG orstep!(sim)for CS. Those functions live inDrivenSimulation.jl.DrivenSimulation.step!refreshes time-varying forcing from the driver, then callsTransportModel.step!or, for binary-scheduled substeps,transport_step!plus an end-of-windowconvection_chemistry_step!.TransportModel.jlis where advection, surface emissions, diffusion, convection, and chemistry are applied to the state.
So, when following a run as a scientist: start here to understand data and configuration flow, then jump to DrivenSimulation.step! and TransportModel.step! to see the actual physics ordering.
GPU residency (feedback_verify_gpu_runs_on_gpu)
When [architecture].use_gpu = true or backend selects a GPU, the runner asserts that state.air_mass lives on the selected backend after model construction and prints a [gpu verified] … line. A silent CPU fallback aborts the run with a precise error message.
AtmosTransport.Models.DrivenRunner.TransportTracerSpec Type
TransportTracerSpecValidated runtime tracer configuration: tracer name, initial-condition configuration, and optional surface-flux configuration.
sourceAtmosTransport.Models.DrivenRunner.run_driven_simulation Method
run_driven_simulation(cfg::AbstractDict) -> TransportModelCanonical high-level entry point for scientists running an AtmosTransport TOML. Use this unless you are writing a custom time loop. It resolves [input] to a sorted binary list, prints a one-line summary for each binary, dispatches on the first binary's grid_type, validates physics-vs-capability, runs the loop, optionally writes topology-native snapshots, and returns the terminal TransportModel.
This function does not call the advection/diffusion/convection kernels directly. The handoff to physics happens inside the structured loop at run_window!(sim) and inside the CS loop at step!(sim). Both routes enter DrivenSimulation.step!, which refreshes forcing and then calls TransportModel.step! / transport_step! / convection_chemistry_step!.
AtmosTransport.Models.DrivenRunner.validate_config Method
validate_config(cfg::AbstractDict) -> (ok::Bool, errors::Vector{String})Run inexpensive pre-flight checks for a driven runtime config: input shape, resolved binary paths, numeric type, backend/float compatibility, tracer table shape, and basic run-window bounds. It does not open binary readers or allocate model state; topology and payload capability checks still run when run_driven_simulation inspects the first binary.