Skip to content

Scattering API

Scattering computes aerosol optical properties, Fourier/Greek coefficients, and phase-matrix reconstructions used by the RT core.

Mie and Aerosol Optics

vSmartMOM.Scattering.make_mie_model Function
julia
make_mie_model(::NAI2, aerosol::Aerosol, λ, polarization, truncation_type, r_max, nquad_radius;
               architecture = Architectures.CPU(), precision_policy = nothing) -> MieModel

Construct a MieModel configured for the Siewert NAI-2 workflow.

Arguments

  • aerosol: aerosol size-distribution and refractive-index specification.

  • λ: wavelength (must use the same length units as r_max and the aerosol radius scale).

  • polarization: one of Stokes_I, Stokes_IQ, Stokes_IQU, Stokes_IQUV.

  • truncation_type: typically δBGE.

  • r_max: upper radius used in size quadrature.

  • nquad_radius: number of radius quadrature points.

Keyword arguments

  • architecture: Architectures.CPU() (default) or Architectures.GPU(). Selects the CPU vs GPU Mie path at compute_aerosol_optical_properties time.

  • precision_policy: GPU Dₙ-recursion precision (NativeFloat64/DSEmulated). nothing (default) auto-selects on the GPU and is ignored on the CPU.

Returns

source
julia
make_mie_model(::PCW, aerosol::Aerosol, λ, polarization, truncation_type, r_max, nquad_radius, wigner_filepath::String) -> MieModel

Construct a MieModel configured for the Domke PCW workflow, loading Wigner tables from wigner_filepath via load_wigner_values.

source
julia
make_mie_model(::PCW, aerosol::Aerosol, λ, polarization, truncation_type, r_max, nquad_radius, wigner_A, wigner_B) -> MieModel

Construct a MieModel configured for the Domke PCW workflow, using precomputed Wigner tables wigner_A and wigner_B.

Use this overload when Wigner tensors are already in memory.

source
vSmartMOM.Scattering.compute_aerosol_optical_properties Function
julia
compute_aerosol_optical_properties(model::MieModel{<:NAI2,FT}, FT_out::Type) -> AerosolOptics

Compute bulk aerosol optical properties with the Siewert NAI-2 formulation on the CPU.

This method is the internal two-argument form called by the architecture/method router (_dispatch_aerosol_optics) in phase_function_autodiff.jl. The router supplies FT_out = _mie_output_type(model) (the model's own FT type parameter) so that a Float32 model produces Float32 greek coefficients. For architecture = GPU() the GPU KernelAbstractions pipeline is dispatched instead (see compute_aerosol_optical_properties_gpu).

The second argument FT_out sets the output float type of the returned AerosolOptics (greek coefficients, ω̃, k). It is supplied by the router and must be passed explicitly — there is no default.

Internal precision: the Mie cross-section sums (S₁, S₂, Cₑₓₜ, Cₛ arrays) and the Greek-coefficient angular quadrature always run in Float64 on the CPU path, regardless of FT. This is intentional — the Dₙ downward continued-fraction recursion and the size-integral sums are catastrophically unstable in Float32 for large or absorbing particles (|y| ≳ 50). The final convert.(FT_out, …) call narrows back to the requested output precision.

Reference:

  • S. Sanghavi, Revisiting the Fourier expansion of Mie scattering matrices in generalized spherical functions, JQSRT 136 (2014), 16-27. https://doi.org/10.1016/j.jqsrt.2013.12.015

  • Cross-section expressions are the standard Mie-series forms (paper Eq. (1)); Greek-coefficient Fourier expansion follows the Siewert/Domke framework discussed around paper Eq. (17).

For each radius quadrature point, Mie coefficients are used to compute extinction and scattering cross-sections:

with  . Bulk values are quadrature-weighted means over the size distribution. The returned optical scalars are:

Greek coefficients (α, β, γ, δ, ϵ, ζ) are then derived from the bulk phase matrix moments (Sanghavi, 2014).

Returns

Notes

  • Uses the convention nᵢ >= 0.

  • Radius and wavelength units must be consistent.

source
julia
compute_aerosol_optical_properties(lin::LinMode, model::MieModel{FDT,FT}, FT2::Type) where {FDT<:NAI2, FT}

Reference: Suniti Sanghavi 2014, https://doi.org/10.1016/j.jqsrt.2013.12.015

Compute the aerosol optical properties and their derivatives (w.r.t. nᵣ, nᵢ, rₚ, σₚ) using the Siewert-NAI2 linearized method.

The second argument FT2 sets the output float type for both the forward greek coefficients and the derivative (lin) greek coefficients. It must be passed explicitly — there is no default. The internal computation always runs in Float64 for numerical stability of the Dₙ recursion (same rationale as the forward path).

Input: LinMode, MieModel Output: (AerosolOptics, linAerosolOptics)

source
julia
compute_aerosol_optical_properties(model::MieModel{<:PCW,FT}, FT2::Type) -> AerosolOptics

Compute bulk aerosol optical properties with the Domke PCW formulation (Sanghavi, 2014), using precomputed Wigner tables.

The second argument FT2 sets the output float type of the returned AerosolOptics. It is supplied by the router (_dispatch_aerosol_optics in phase_function_autodiff.jl) and must be passed explicitly — there is no default.

Reference:

The method evaluates terms (Eq. 22 in Sanghavi, 2014), maps them to Greek coefficients (Eq. 24), and returns AerosolOptics with:

Use make_mie_model with PCW() and Wigner inputs before calling this function.

There is no GPU PCW kernel; a GPU()-architecture PCW model falls back to this CPU implementation (with a one-time @warn) via the single-verb compute_aerosol_optical_properties(model) router.

source
julia
compute_aerosol_optical_properties(model::MieModel; autodiff=false) -> AerosolOptics

Single-verb entry point for aerosol optics. Everything (Fourier-decomposition method, compute architecture, GPU precision policy) is read off the model.

  • autodiff=false (default): dispatches on model.computation_type and model.architecture:

    • NAI2 + CPU() → the analytic CPU implementation (compute_aerosol_optical_properties 2-arg method).

    • NAI2 + a GPU architecture with a Mie pipeline (has_gpu_mie true, i.e. CUDA GPU()) → the KernelAbstractions GPU pipeline (compute_aerosol_optical_properties_gpu).

    • NAI2/PCW + a non-CPU architecture without a GPU Mie pipeline (e.g. MetalGPU()) → one-time @warn then CPU fallback (Mie on CPU; RT arrays still run on that architecture).

    • PCW + GPU → one-time @warn then CPU fallback (no GPU PCW kernel).

    • PCW + CPU() → the analytic PCW implementation.

  • autodiff=true: computes the Jacobian with respect to the 4 aerosol parameters   using ForwardDiff. AD always runs on the CPU analytic kernel (Dual numbers do not flow through the GPU kernels).

The AD Jacobian is stored in AerosolOptics.derivs with shape (6L + 2, 4), where L is the Greek coefficient length and rows are stacked as [α; β; γ; δ; ϵ; ζ; ω̃; k].

source
vSmartMOM.Scattering.truncate_phase Function
julia
truncate_phase(::NoTruncation, aero::AerosolOptics; kwargs...) -> AerosolOptics

Identity passthrough. Returns an AerosolOptics with the same Greek coefficients, ω̃ and k, and fᵗ = 0 (the f_tr → 0 limit of Sanghavi & Stephens 2015 Eq. 8 — the truncation-modified τ*, ω*, Z* collapse to the originals).

Note: raw Mie outputs initialise fᵗ = 1 as a "untruncated yet" sentinel — passing them through unchanged would let downstream delta_m_forward interpret the 1 as "everything is in the forward peak" and silently zero out aerosol scattering. We return fᵗ = 0 so the rescaling is a true no-op.

source
julia
truncate_phase(mod::δBGE, aero::AerosolOptics; reportFit=false) -> AerosolOptics

Apply δ-BGE truncation to aerosol Greek coefficients.

The method removes/approximates the forward peak using a least-squares fit over angles outside Δ_angle, then renormalizes with retained scattering fraction :

Returns a new AerosolOptics with truncated coefficients and updated fᵗ.

source
julia
truncate_phase(mod::δBGE, aero::AerosolOptics, lin_aero::linAerosolOptics; reportFit=false)

Apply δ-BGE truncation to aerosol optics and their linearized derivatives (Jacobians).

Performs the same least-squares fit as truncate_phase(mod::δBGE, aero) for β, γ, ϵ, then propagates derivatives through the truncation to obtain truncated Greek-coefficient Jacobians. Reference: Sanghavi & Stephens (2015).

Arguments

  • mod: δBGE with l_max and Δ_angle

  • aero: AerosolOptics to truncate

  • lin_aero: linAerosolOptics with derivatives w.r.t. state (e.g. nᵣ, nᵢ, r)

  • reportFit: if true, print RMS fit errors

Returns

  • (AerosolOptics, linAerosolOptics): truncated optics and their derivatives
source
julia
truncate_phase(::NoTruncation, aero::AerosolOptics, lin_aero::linAerosolOptics; kwargs...)
    -> (AerosolOptics, linAerosolOptics)

Identity passthrough for the linearised (Jacobian) path. Resets the raw Mie sentinel fᵗ = 1 (and the corresponding ḟᵗ) to zero, matching the two-argument truncate_phase(::NoTruncation, aero) so delta_m_truncation_lin doesn't silently zero the aerosol SSA Jacobian when params.truncation = NoTruncation().

source

Output Types

vSmartMOM.Scattering.GreekCoefs Type
julia
GreekCoefs{FT<:Real}

Expansion coefficients of the 4×4 scattering (phase) matrix in generalised spherical functions (the "Greek" coefficients). Six independent coefficient vectors (α, β, γ, δ, ϵ, ζ) fully describe the azimuthal Fourier decomposition of the scattering matrix B for a given particle or mixture. See Eq. 16 in Sanghavi (2014) for the mapping to B elements.

For scalar (intensity-only) RT, only β (the phase-function expansion) is used.

Fields

  • α: Greek matrix coefficient α, is in B[2,2]

  • β: Greek matrix coefficient β, is in B[1,1] (only important one for scalar!)

  • γ: Greek matrix coefficient γ, is in B[2,1],B[1,2]

  • δ: Greek matrix coefficient δ, is in B[4,4]

  • ϵ: Greek matrix coefficient ϵ, is in B[3,4] and - in B[4,3]

  • ζ: Greek matrix coefficient ζ, is in B[3,3]

source
vSmartMOM.Scattering.Aerosol Type
julia
Aerosol

Aerosol microphysical properties: particle size distribution and complex refractive index. Used as input to MieModel for computing single-scattering optical properties via Lorenz-Mie theory.

The refractive index convention is n = nᵣ - i·nᵢ, where positive nᵢ indicates absorption.

The struct is parameterized by the refractive-index element type FT. FT is typically a plain AbstractFloat (Float64/Float32) but may also be a ForwardDiff.Dual so the autodiff path can track derivatives with respect to nᵣ/nᵢ; for that reason FT is intentionally not constrained to <:AbstractFloat. The outer convenience constructor Aerosol(dist, nᵣ, nᵢ) promotes nᵣ and nᵢ to a common type, so existing call sites continue to work unchanged.

Fields

  • size_distribution::ContinuousUnivariateDistribution: Particle radius distribution (e.g., LogNormal). Units: μm.

  • nᵣ::FT: Real part of the refractive index (relative to air).

  • nᵢ::FT: Imaginary part of the refractive index (absorption).

Example

julia
using Distributions
aer = Aerosol(LogNormal(log(0.3), 0.4), 1.3, 0.01)
source
vSmartMOM.Scattering.AerosolOptics Type
julia
AerosolOptics{FT<:Real}

Computed aerosol single-scattering optical properties for one aerosol type at one (or more) wavelengths. Produced by integrating the Mie solution over the particle size distribution.

Fields

  • greek_coefs: Greek matrix

  • ω̃: Single Scattering Albedo

  • k: Extinction cross-section

  • fᵗ: Truncation factor

  • derivs: Derivatives

source

Fourier Decomposition Modes

vSmartMOM.Scattering.NAI2 Type
julia
type NAI2

Perform Siewart's numerical integration method, NAI-2, to compute aerosol phase function decomposition. See: http://adsabs.harvard.edu/full/1982A%26A...109..195S

source
vSmartMOM.Scattering.PCW Type
julia
type PCW

Perform Domke's Precomputed Wigner Symbols method, PCW, to compute aerosol phase function decomposition. See: http://adsabs.harvard.edu/full/1984A%26A...131..237D

source

Phase-function Truncation

vSmartMOM.Scattering.AutoTruncation Type
julia
AutoTruncation()

Phase D — deferred-decision marker for truncation: auto in YAML (mirrors VLIDORT's DO_DELTAM_SCALING philosophy). At model_from_parameters time it resolves deterministically:

  • No aerosol scattering, or all aerosols' length(greek.β) - 1 fits within stream_l_capNoTruncation() (typical for Rayleigh-only or smooth-aerosol scenes).

  • Aerosols with phase_lmax > stream_l_capδBGE(stream_l_cap, Δ_angle).

The resolver emits an @info line stating which branch was taken so the user can always see what was applied. AutoTruncation is deliberately not threaded through the Mie/RT kernels — it is a build-time placeholder that gets replaced before any kernel sees it.

User-facing knobs in YAML:

ValueMeaning
truncation: autoThis deferred-decision mode (Phase D recommended)
truncation: NoTruncation() / nullExactly no transform; errors if coefs exceed cap
truncation: δBGE(N, Δ)Explicit; used for benchmarks / cross-validation
source