CoreRT API
CoreRT owns the adding-doubling solver, the RT model containers, and the linearized/Jacobian-facing model layout.
Forward and Linearized Modes
vSmartMOM.FwdMode Type
FwdMode()Marker selecting the forward radiative-transfer model construction path.
sourcevSmartMOM.LinMode Type
LinMode()Marker selecting the linearized model construction path used for Jacobians.
sourcevSmartMOM.CoreRT.model_from_parameters_lin Function
model_from_parameters_lin(params)Convenience alias for model_from_parameters(LinMode(), params). Returns (model, lin_model).
vSmartMOM.CoreRT.rt_run_lin Function
rt_run_lin(model, lin_model, NAer, NGas, NSurf; i_band=1)Convenience alias for the linearized rt_run overload. Equivalent to rt_run(model, lin_model, NAer, NGas, NSurf; i_band).
Model Types
vSmartMOM.CoreRT.RTModel Type
RTModel{ARCH, FT} <: AbstractRTModel{ARCH, FT}Central model state for vSmartMOM radiative transfer.
Only two type parameters:
ARCH: compute architecture (CPUorGPU)FT: floating-point precision (Float32orFloat64)
All physics sub-components are organized hierarchically:
solver: RT solver configuration (polarization, quadrature, truncation)geometry: observation geometry (SZA, VZA, VAZ, observer altitude)quad_points: precomputed quadrature points and weightsatmosphere: atmospheric state (profile + spectral bands)optics: all precomputed optical properties (Rayleigh, aerosol, absorption)surfaces: per-band surface BRDF models
Fields
architecture: Compute architecture (CPU/GPU)solver: RT solver configurationnumerics: Numerical-knob parameters (doubling threshold, etc.) — seeRTNumericalParametersgeometry: Observation geometryquad_points: Quadrature points and weightsatmosphere: Atmospheric state (profile + spectral bands)optics: Precomputed optical propertiessurfaces: Surface models, one per spectral bandsources: Source-term scene (v0.6 source-term refactor). Defaults to a singleSolarBeam— i.e. the historical unit-Stokes-I direct solar illumination — and can be overridden atrt_runcall time via thesources=kwarg. Mirrors the abstract-typedsurfacesslot.
vSmartMOM.CoreRT.SolverConfig Type
SolverConfig{FT, PT, QT}Immutable RT solver configuration: polarization mode, quadrature scheme, Fourier truncation, and Legendre truncation. Fixed after model construction; never differentiated.
Fields
polarization_type: Type of polarization (Stokes_I / IQU / IQUV)quadrature_type: Quadrature type (RadauQuad / GaussLegQuad)m_max_bands: Per-band Fourier loop bound, order semantics: loop runsm = 0:m_max_bands[iBand]. Equalsn_fourier_moments_bands .- 1.n_fourier_moments_bands: Per-band Fourier moment count:n_fourier_moments_bands[iBand] = m_max_bands[iBand] + 1. Provided so consumers don't have to remember the count↔order convention.l_max: Per-band max truncated Legendre indexl_trunc: Legendre truncation order (user-specified)Δ_angle: Exclusion angle for forward peak [deg]depol: Depolarization factoruse_component_traits: Phase C flag: whentrue(current default), per-bandm_max_bandsare derived fromcomponent_m_max(c, ctx)traits across active components — Cox-Munk / RPV / RossLi / canopy run to their fulluser_l_capinstead of the historical half-truncated aggregator. Flip tofalseto fall back to the legacymin(ceil((l_max+1)/2), params.max_m)aggregator (bit-equal to Phase B).
vSmartMOM.CoreRT.Atmosphere Type
Atmosphere{FT, VMR}The atmospheric column: profile data plus spectral grid definitions.
Fields
profile: Atmospheric profile (T, p, q, vmr, vcd, etc.)spec_bands: Spectral bands — Vector of wavenumber grids, one per band
vSmartMOM.CoreRT.RayleighScattering Type
RayleighScattering{FT, GC}Precomputed Rayleigh and Cabannes (elastic) scattering properties. Derived from the depolarization ratio; fixed for a given spectral band.
Fields
greek_rayleigh: Greek coefficients for total Rayleigh scattering (single set or per-band)greek_cabannes: Greek coefficients for Cabannes (pure elastic) Rayleigh per bandϖ_Cabannes: Pure elastic (Cabannes) fraction of Rayleigh scattering per band
vSmartMOM.CoreRT.AerosolState Type
AerosolState{FT, AO}Per-band aerosol scattering optics and optical depth profiles. Primary differentiable state for aerosol retrievals.
Fields
aerosol_optics: Truncated aerosol optics: aerosol_optics[iBand][iAer]τ_aer: Aerosol optical depth profiles:τ_aer[iBand][iAer, nSpec, iLayer]— 3-D for both the forward and linearized paths, enabling per-wavelength aerosol optical depth within wide spectral bands.
vSmartMOM.CoreRT.Optics Type
Optics{FT, RS, AS}Container for all precomputed optical properties that feed into the RT solver. Groups Rayleigh scattering, aerosol scattering, absorption optical depths, and Rayleigh optical depths.
AD boundary: aerosols and τ_abs hold differentiable state; rayleigh and τ_rayl are typically fixed.
Fields
rayleigh: Rayleigh/Cabannes scattering propertiesaerosols: Aerosol scattering optics and optical depthsτ_abs: Absorption optical depth: τ_abs[iBand][nSpec × nLayers]τ_rayl: Rayleigh optical depth: τ_rayl[iBand][nSpec × nLayers]
vSmartMOM.CoreRT.OpticsLin Type
OpticsLin{FT}Linearized (Jacobian) counterpart of Optics. Each field stores derivatives of the corresponding forward-model field with respect to the physical state vector.
Fields
τ̇_abs: ∂τ_abs/∂x per band: Vector of arrays [NGas × nSpec × nLayers]τ̇_aer: ∂τ_aer/∂x per band: Vector of arrays [NAer × 7 × nSpec × nLayers]lin_aerosol_optics: Linearized aerosol optics per band per aerosol
vSmartMOM.CoreRT.vSmartMOM_Parameters Type
vSmartMOM_Parameters{FT<:Real}Top-level container for all user-specified model parameters before any derived quantities are computed. Groups radiative-transfer settings (spectral bands, BRDF, quadrature, polarization), observation geometry (SZA, VZA, VAZ), the atmospheric profile (T, p, q), and optional absorption/scattering sub-parameter structs.
Fields
spec_bands: Spectral bands — Vector of wavenumber grids, one per bandbrdf: Surface (Bidirectional Reflectance Distribution Function)quadrature_type: Quadrature type for RT streams (RadauQuad/GaussLegQuad)polarization_type: Type of polarization (I/IQ/IQU/IQUV)max_m: Hard cutoff for maximum number of Fourier moments to loop overΔ_angle: Exclusion angle for forward peak in degrees (legacy — seetruncation)l_trunc: Truncation length for legendre terms (scalar for now, can donBandlater)truncation: Phase-function truncation method. Defaults toδBGE(l_trunc, Δ_angle)for backward compatibility; set explicitly toNoTruncation()for canopy-only or smooth-phase-function runs (Sanghavi & Stephens 2015 §2 — thef_tr → 0limit). TheΔ_anglefield above is then ignored.depol: Depolarization factornumerics: Numerical-knob parameters (doubling threshold, etc.) — defaults toRTNumericalParameters{FT}()if not specified in YAML.float_type: Float type to use in the RT (Float64/Float32)architecture: Architecture to use for calculations (CPU/GPU)sza: Solar zenith angle [deg]vza: Viewing zenith angles [deg]vaz: Viewing azimuthal angles [deg]obs_alt: Altitude of observer [Pa]T: Temperature Profile [K]p: Pressure Profile [hPa]q: Specific humidity profileprofile_reduction_n: Length of profile reductionabsorption_params: Optional struct that holds all absorption-related parametersscattering_params: Optional struct that holds all aerosol scattering-related parametersnstreams: Phase D — primary user-facing resolution knob: weighted streams per hemisphere. Public contract:stream_l_cap = 2·nstreams - 1. Whennothing, the parser populatedmax_m/l_truncfrom a legacy YAML; new-schema configs set this and may omitmax_m/l_trunc.m_max_override: Phase D — explicit per-band Fourier loop bound (order, optional). When set, clamps the trait-aggregator output. Lower hard cap on top ofstream_l_cap.stream_l_cap: Phase D — derived projection cap:2·nstreams - 1for new schema, orl_truncfor legacy. Internally consumed by the trait aggregator and the truncation-resolver. Always populated; defaults tol_truncuntilnstreamsis explicitly set.legacy_l_cap_override: Phase D — legacyl_truncvalue retained verbatim from YAML when the user explicitly set it.nothingfor new-schema configs that derivestream_l_capfromnstreamsinstead.
vSmartMOM.CoreRT.AtmosphericProfile Type
AtmosphericProfile{FT, VMR}Vertical atmospheric state on a pressure grid, ordered from TOA to BOA.
Stores temperature, pressure (full levels and half levels), humidity, dry and wet vertical column densities, and volume mixing ratios for trace gases. Constructed internally by model_from_parameters from the raw arrays in vSmartMOM_Parameters.
p_full has N levels; p_half has N-1 layer-boundary pressures. T, q, vmr_h2o, vcd_dry, vcd_h2o, and Δz are layer quantities of length N.
Fields
T: Temperature Profilep_full: Pressure Profile (Full)q: Specific humidity profilep_half: Pressure Levelsvmr_h2o: H2O Volume Mixing Ratio Profilevcd_dry: Vertical Column Density (Dry)vcd_h2o: Vertical Column Density (H2O)vmr: Volume Mixing Ratio of Constituent GasesΔz: Layer height (meters)
vSmartMOM.CoreRT.QuadPoints Type
QuadPoints{FT}Gauss or Gauss-Radau quadrature points and weights used for the angular discretisation of the radiative transfer equation. Also stores the cosine of the solar zenith angle (μ₀) and its index within the quadrature grid.
Fields
μ₀: μ₀, cos(SZA)iμ₀: Index in quadrature points with suniμ₀Nstart: Index in quadrature points with sun (in qp_μN)qp_μ: Quadrature pointswt_μ: Weights of quadrature pointsqp_μN: Quadrature points (repeated for polarizations)wt_μN: Weights of quadrature points (repeated for polarizations)Nquad: Total number of quadrature points (weighted streams + zero-weight SZA/VZA output nodes)Nstreams: Number of weighted streams per hemisphere (count of nonzero weights). Public contract: stream_l_cap = 2·Nstreams - 1.
vSmartMOM.CoreRT.CompositeLayer Type
CompositeLayer{FT} <: AbstractLayerAccumulated (composite) layer matrices produced by the interaction step of the adding/doubling RT method. Stores the reflectance (R), transmission (T), and source (J) matrices for the combined atmospheric slab from the top of atmosphere down to the current layer.
Sign convention: − = outgoing (upward, decreasing τ), + = incoming (downward, increasing τ).
Fields
R⁻⁺::AbstractArray{FT,3}: reflectance from incoming (+) to outgoing (−)R⁺⁻::AbstractArray{FT,3}: reflectance from outgoing (−) to incoming (+)T⁺⁺::AbstractArray{FT,3}: transmission in the incoming (+) directionT⁻⁻::AbstractArray{FT,3}: transmission in the outgoing (−) directionJ₀⁺::AbstractArray{FT,3}: source in the incoming (+) directionJ₀⁻::AbstractArray{FT,3}: source in the outgoing (−) direction
vSmartMOM.CoreRT.AddedLayer Type
AddedLayer{FT} <: AbstractLayerSingle homogeneous layer matrices produced by the elemental/doubling steps of the RT solver. After doubling, these represent a full atmospheric layer that is subsequently combined with the composite layer via the interaction step.
Lower-case field names (r, t, j) distinguish added-layer quantities from composite-layer quantities (R, T, J).
Fields
r⁻⁺::AbstractArray{FT,3}: reflectance from incoming (+) to outgoing (−)t⁺⁺::AbstractArray{FT,3}: transmission in the incoming (+) directionr⁺⁻::AbstractArray{FT,3}: reflectance from outgoing (−) to incoming (+)t⁻⁻::AbstractArray{FT,3}: transmission in the outgoing (−) directionj₀⁺::AbstractArray{FT,3}: source in the incoming (+) directionj₀⁻::AbstractArray{FT,3}: source in the outgoing (−) directiontemp1,temp2: pre-allocated workspace arrays to avoid allocationstemp1_ptr,temp2_ptr: CUDA pointer arrays (ignored on CPU)
vSmartMOM.CoreRT.RTNumericalParameters Type
RTNumericalParameters{FT}Centralised home for tunable numerical knobs that were previously hardcoded in the RT kernels. Lives once on vSmartMOM_Parameters / RTModel, threaded through to the kernels where needed. Designed to grow as more constants are lifted (Glint Legendre expansion cap, etc.).
Fields
dτ_max_threshold: Doubling resolution: cap on the elemental-layer optical depthdτ_max = threshold · μ_min, whereμ_minis the smallest TRUE (positive-weight) quadrature stream cosine. Smaller values produce finer initial layers (more doublings → more accurate single-scatter at the cost of more roundoff through doubling). Default0.001is conservative legacy; raising to~0.01reduces doubling iterations.dτ_min_floor: Absolute floor ondτ_max(and hence ondτ_initial), expressed as a multiple ofeps(FT). Prevents the doubling discretisation from collapsing below FT precision regardless of geometry. Default1024·eps(FT)≈ 1.2e-4 for Float32 / 2.3e-13 for Float64 — the F32 value capsndoublaround 13–14 for τ_total≤1 (well within Float32 representability); the F64 value is far below any sensiblethreshold·μ_minso it never activates in practice.blas_threads: BLAS thread cap applied at everyrt_runinvocation.nothingmeans leave the BLAS thread setting alone (use whateverLinearAlgebra.BLAS.get_num_threads()returned at session start). Why cap: the batched-GEMM call sites incpu_batched.jland the elemental/doubling/interaction kernels operate on small matrices (NSTREAMS·n_stokes ≈ 12-48 per side) tiled across a wide spectral batch. Multi-threaded BLAS coordination dominates the work at that matrix size and serializes against the spectral-batch parallelism. The VLIDORT baseline harness empirically picked 8 as the sweet spot on a 128-thread machine;1is the most defensive choice when a single process owns all spectral points and threading happens at the batched outer level. Set via thenumerics.blas_threadsYAML key, or programmatically withRTNumericalParameters{FT}(blas_threads = 8).verbose: Verbose output flag. Whenfalse(default)rt_run/rt_run_linsuppress the per-callprint_timer()dump at the end of the run. Settrue(YAML keynumerics.verbose: trueor programmaticallyRTNumericalParameters{FT}(verbose = true)) to bring back the timing tree — useful for profiling, noisy for production loops. Per-bandComputing profile for X...andAOD at band X...messages were demoted to@debugand are silent unless you setENV["JULIA_DEBUG"] = "vSmartMOM".
Source-term types (
SolarBeam,BlackbodySource,SurfaceSIF,SourceSet,NoSource, AD-mode traits,prepare_source/surface_source_contribute!dispatchers) are documented on the Source terms page.
Batch Scene Processing
BatchContext enables efficient multi-scene loop workflows (e.g. ensemble retrievals, parameter sweeps) by caching expensive one-time setup work (Mie, Fourier decomposition, HITRAN parsing) and exposing cheap per-scene update functions.
vSmartMOM.CoreRT.BatchContext Type
BatchContextPre-built context for efficient batch radiative-transfer over many atmospheric scenes that share the same spectral configuration, geometry, surface BRDF, aerosol microphysics, and quadrature setup but differ in temperature/pressure profiles, humidity, and/or trace-gas VMRs.
Construct once from a vSmartMOM_Parameters object; then call update_model! before each rt_run invocation.
Example usage
params = parameters_from_yaml("my_config.yaml")
ctx = BatchContext(params)
for scene in scenes
update_model!(ctx;
T = scene.T, # length-Nz temperature profile [K]
p_half = scene.p_half, # length-(Nz+1) half-level pressures [hPa]
q = scene.q, # length-Nz specific humidity [kg/kg]
vmr = scene.vmr) # Dict{String,Any} — same keys as params.absorption_params.vmr
R, T = rt_run(ctx.model)
# ... process R, T ...
endWhat may change per scene
Temperature profile
T[K]Pressure half-levels
p_half[hPa]Specific humidity
q[kg/kg]Trace-gas VMRs via the
vmrkeyword dict (same keys as the originalparams.absorption_params.vmr; adding new species requires a full rebuild)
What requires a full rebuild (new BatchContext)
Spectral bands (
params.spec_bands)Geometry (SZA, VZA, VAZ, observer altitude)
Surface BRDF
Polarization type, quadrature type, truncation
A different number of aerosols or gas species
Aerosol changes do not require a rebuild: use update_aerosol_loading! for τ_ref / vertical-placement changes (cheap, no Mie recomputation) and update_aerosol_microphysics! for size-distribution / refractive-index changes (reruns Mie for that aerosol and re-derives the Fourier-loop bounds).
Thread safety
One BatchContext per thread. update_model! and rt_run(ctx.model) mutate shared arrays and must not be called concurrently on the same ctx. If you run parallel scenes, create one BatchContext per worker thread (each BatchContext owns its own RTModel with independent mutable arrays).
Fields
model: theRTModelthat is updated in place byupdate_model!params: the originalvSmartMOM_Parametersused for construction (kept for meta-information such as molecule lists, YAML knobs, float type)absorption_models: cachedAtmosphericAbsorption.LineByLineModelobjects, one per(band, species)pair — eliminates HITRAN re-parsing per sceneh2o_models: cached H₂OLineByLineModelper band (nothingonly when the configuration has noabsorption_paramsat all; otherwise the model is cached unconditionally so a scene whoseqchanges from all-zero to non-zero can apply H₂O line absorption without a rebuild)k_ref: reference-wavelength aerosol extinction coefficients, one per aerosol species (needed for Phase 2 aerosol-loading updates)current_T,current_p_half,current_q,current_vmr: the unreduced scene state thatupdate_model!was last called with (initialised fromparamsat construction).nothingkeyword arguments toupdate_model!fall back to these stored values — never toparams— so successive partial updates compose incrementally. Stored already FT-converted so repeated updates do not re-convert or drift. The unreduced state cannot be recovered frommodel.atmosphere.profile(which is reduced), which is why it lives here.current_τ_ref,current_profile_dist: the current per-aerosol loading state (column optical depth atλ_refand vertical distribution), initialised fromparamsand written by bothupdate_aerosol_loading!andupdate_aerosol_microphysics!.update_model!'s τ_aer redistribution reads these so a prior loading update is not silently wiped.n_bands,n_aerosols,Nz: scene-invariant dimension bookmarksprofile_reduction_n: reduction target passed toreduce_profile;-1means no reduction
vSmartMOM.CoreRT.update_model! Function
update_model!(ctx::BatchContext;
T = nothing,
p_half = nothing,
q = nothing,
vmr = nothing)Update ctx.model in place for a new atmospheric scene.
Only the arguments you supply are updated. nothing for a field means "keep the current scene value" — i.e. the value from the most recent successful update_model! call (or, if none yet, the value the BatchContext was built with). It does not fall back to the original params. This makes successive partial updates compose incrementally:
update_model!(ctx; vmr = B) # vmr = B, everything else still original
update_model!(ctx; T = C) # T = C AND vmr is still B (not reset to original)The merge is per-field: T, p_half, q, and the vmr override dict are each remembered on the context (ctx.current_T, ctx.current_p_half, ctx.current_q, ctx.current_vmr) and overwritten only by the fields you pass. The remembered state is stored unreduced and already converted to the model's float type (params.float_type), so repeated updates neither re-convert nor drift.
For vmr, the supplied keys are overlaid onto the current override dict (which itself started as params.absorption_params.vmr); keys you do not pass keep their last value. The merged overrides are then layered over the configured defaults exactly as model_from_parameters does.
After this call rt_run(ctx.model) will produce radiances for the new scene.
Keyword arguments
T::AbstractVector: Temperature profile [K], lengthNz(full levels, TOA to BOA). Ifprofile_reduction_n != -1, pass the unreduced profile length (same as the originalparams.T).p_half::AbstractVector: Half-level pressures [hPa], lengthNz + 1(orN_orig + 1before reduction). Must be strictly positive and monotonically increasing (TOA to BOA, i.e.p_half[end]is surface pressure).q::AbstractVector: Specific humidity [kg/kg], lengthNz(orN_orig).vmr::Dict{String,Any}: Trace-gas volume mixing ratios. Keys must be a subset of the configured molecules — supplying an unknown species key raises an error (add it toparams.absorption_params.vmrand rebuild the context instead). Values may be scalars or length-Nzvectors.
Thread safety
update_model! and rt_run(ctx.model) share mutable arrays. Do not call them concurrently on the same ctx. Use one BatchContext per thread for parallelism.
Example
params = parameters_from_yaml("config.yaml")
ctx = BatchContext(params)
for scene in scenes
update_model!(ctx;
T = scene.T,
p_half = scene.p_half,
q = scene.q,
vmr = Dict("O2" => 0.21, "CH4" => scene.ch4_vmr))
R, T_trans = rt_run(ctx.model)
endvSmartMOM.CoreRT.update_aerosol_loading! Function
update_aerosol_loading!(ctx::BatchContext, i_aer::Int;
τ_ref = nothing,
profile_dist = nothing)Cheap path — update only the column-integrated optical depth (τ_ref) and/or the vertical pressure distribution (profile_dist) for aerosol species i_aer, using the cached aerosol optics (aerosol_optics) and reference extinction coefficient (ctx.k_ref[i_aer]). No Mie recomputation is performed.
After this call rt_run(ctx.model) produces radiances for the new aerosol loading. All other model state (gas absorption, profile, surface) is unchanged.
Keyword arguments
τ_ref::Real: New column optical depth atλ_ref. Whennothing, the value stored inparams.scattering_params.rt_aerosols[i_aer].τ_refis kept (only the distribution is updated).profile_dist::Distributions.Distribution: New vertical pressure distribution (aDistributions.jlDistributionobject — the same type used inRT_Aerosol.profile). Whennothing, the existing distribution is kept.
Cost
O(Nz) per band — evaluates the distribution PDF on the pressure grid and scales the optical depth profile. No Mie, no HITRAN.
What it invalidates
model.optics.aerosols.τ_aer[i_band][i_aer, :, :]— all bands (3-D: nSpec × nLayers).Does NOT change
aerosol_optics,k_ref,SolverConfigFourier bounds, gas absorption, or Rayleigh properties.
Example
ctx = BatchContext(params)
# Change τ_ref for aerosol 1 to 0.3, keep vertical distribution
update_aerosol_loading!(ctx, 1; τ_ref = 0.3)
R, T = rt_run(ctx.model)vSmartMOM.CoreRT.update_aerosol_microphysics! Function
update_aerosol_microphysics!(ctx::BatchContext, i_aer::Int, aerosol::Aerosol;
τ_ref = nothing)Expensive path — replace the microphysics of aerosol species i_aer with a new Aerosol (new size distribution and/or refractive index) and recompute all derived quantities via the same Mie code path that model_from_parameters uses.
This updates:
model.optics.aerosols.aerosol_optics[i_band][i_aer]for every bandctx.k_ref[i_aer](the new reference-wavelength extinction coefficient)model.solver.m_max_bands,n_fourier_moments_bands,l_max(in-place via.=) — the critical Fourier-loop re-derivation that prevents silent wrong results when the new particle size changes the length of the Greek- coefficient series.model.optics.aerosols.τ_aer[i_band][i_aer, :, :]for every band (3-D: nSpec × nLayers).
After this call rt_run(ctx.model) gives the same result as building a fresh model with the new aerosol.
Arguments
ctx: TheBatchContextto update.i_aer: 1-based index of the aerosol species to replace.aerosol: NewAerosol(fromScattering.Aerosol), carrying the newsize_distribution,nᵣ, andnᵢ.
Keyword arguments
τ_ref::Real: New column optical depth atλ_ref. Whennothing, the current scene valuectx.current_τ_ref[i_aer]is kept (i.e. the most recently applied loading, not the originalparamsvalue).
SolverConfig mutability note
SolverConfig is an immutable struct, but its three Vector fields (m_max_bands, n_fourier_moments_bands, l_max) are mutable Julia arrays and are updated in-place with .=. The scalar fields (l_trunc, Δ_angle, depol, polarization_type, quadrature_type) cannot be changed in-place; they are guaranteed to be unaffected by aerosol microphysics changes since they derive from params, not from per-aerosol optics. If a caller somehow requires a new l_trunc or Δ_angle, a full model_from_parameters rebuild is necessary.
Cost
Full Mie per band (O(n_bands × nquad_radius × size_distribution_points)), i.e. the same cost as the aerosol section of model_from_parameters.
What it invalidates
aerosol_optics[i_band][i_aer]— all bands.ctx.k_ref[i_aer].solver.m_max_bands,solver.n_fourier_moments_bands,solver.l_max.τ_aer[i_band][i_aer, :, :]— all bands (3-D: nSpec × nLayers).
Example
ctx = BatchContext(params)
# Save initial state for comparison
R_A, _ = rt_run(ctx.model)
# Replace aerosol 1 with larger particles (reff ~2 μm)
new_aerosol = Aerosol(LogNormal(log(2.0), 0.4), 1.3, 1e-8)
update_aerosol_microphysics!(ctx, 1, new_aerosol; τ_ref = 0.1)
R_B, _ = rt_run(ctx.model)Stream-Level RT Output
vSmartMOM.CoreRT.StreamRTResult Type
StreamRTResult{FT}Per-Fourier-moment radiative-transfer result at all internal quadrature streams — the output of rt_run_streams. Downstream consumers (e.g. ExoOptics disk integration) reconstruct the Stokes vector at arbitrary (μ_v, μ_0, Δφ) by interpolating over (μ_v, μ_0) and Fourier-summing over m with cos(m·Δφ) / sin(m·Δφ) weights, instead of one rt_run per pixel.
Fields
qp_μ :: Vector{FT}— full quadrature mu nodes (lengthNquad).iμ₀ :: Int— index intoqp_μof the SZA stream (the closest toμ₀).μ₀ :: FT— cosine of the chosen incident-beam SZA.pol_n :: Int— number of Stokes components (pol_type.n).weight :: Vector{FT}— Fourier weight(0.5/π for m=0; 1/π otherwise)used for each moment by the internal post-processor.R⁻⁺_per_m :: Vector{Array{FT, 3}}—(NquadN, NquadN, nSpec)per Fourier moment, whereNquadN = Nquad · pol_n. This is the full-stream reflection matrix (stokes-out blocks × stokes-in blocks).J⁻_per_m :: Vector{Array{FT, 3}}—(NquadN, 1, nSpec)per Fourier moment, the combined per-source SFI Stokes at all output streams (legacy slot + all per-source slots summed). Use this when you want the SFI-style output without re-running RT.J⁺_per_m :: Vector{Array{FT, 3}}— analog for BOA transmittance.
Recovering rt_run's output
streams = rt_run_streams(model; sources = sources)
# At a single (vza, vaz):
iμ = nearest_point(streams.qp_μ, cosd(vza))
_, istart, iend = get_indices(iμ, pol_type)
R_recovered = zero(rt_run(model; sources)[1][1, :, :]) # (n_stokes, nSpec)
for (mi, m) in enumerate(0:length(streams.J⁻_per_m)-1)
cosmφ = cosd(m * vaz); sinmφ = sind(m * vaz)
w_stokes = pol_n == 1 ? streams.weight[mi] * cosmφ :
streams.weight[mi] *
Diagonal([cosmφ, cosmφ, sinmφ, sinmφ][1:pol_n])
for s in 1:nSpec
R_recovered[:, s] .+= w_stokes * streams.J⁻_per_m[mi][istart:iend, 1, s]
end
endA unit test pins the bit-exact agreement of this reconstruction against rt_run for one published-figure geometry.
vSmartMOM.CoreRT.rt_run_streams Method
rt_run_streams(model; i_band=1, sources=nothing) -> StreamRTResultRun the RT solver and return per-Fourier-moment Stokes matrices at all quadrature streams instead of post-processed (vza, vaz) outputs. See StreamRTResult for the data layout and a worked recovery example.
Internally just calls rt_run with a streams_callback that copies composite_layer.R⁻⁺, composite_layer.J₀⁺/⁻, and the combined per-source-slot SFI contributions out of the live layer accumulators once per Fourier moment.
Jacobian Parameter Layout
vSmartMOM.CoreRT.ParameterLayout Type
ParameterLayoutDescribes the ordering of physical parameters in the Jacobian derivative dimension.
Instead of hardcoding 7*NAer + NGas + NSurf throughout the codebase, all index arithmetic goes through this struct. Each aerosol carries aerosol_params sub-parameters (currently 7: τ_ref, nᵣ, nᵢ, rₘ, σ_g, p₀, σ_p), followed by one slot per gas VMR and one per surface parameter.
Example
layout = ParameterLayout(n_aerosols=1, n_gases=2, n_surface=1)
aerosol_range(layout, 1) # 1:7
gas_range(layout) # 8:9
surface_range(layout) # 10:10
n_total(layout) # 10vSmartMOM.CoreRT.surface_index Function
Index of a specific surface parameter (1-based within the surface block).
sourcevSmartMOM.CoreRT.n_layer_params Function
Number of layer-level parameters (aerosol + gas, excluding surface and canopy).
sourcevSmartMOM.CoreRT.canopy_range Function
Index range for canopy parameters (LAI, leaf_R, leaf_T, ...).
source