Conventions
For: anyone cross-validating vSmartMOM against another RT code (VLIDORT, DISORT, …) or importing Greek-coefficient / Stokes data from one.
Next: Configure a Scene (step by step), Vector RTE & Discretization (Concepts), Benchmarks.
Polarized radiative transfer codes have to commit to a specific set of sign, phase-matrix, and angle conventions. Different lineages (vSmartMOM's de Rooij/Hovenier-style code convention, Siewert–Mishchenko–VLIDORT, Stamnes–DISORT, …) made different choices, and the choices are largely interchangeable as long as you stay inside one convention. The pain hits when you cross-validate two codes that quietly follow different conventions.
This page first lays out the conventions vSmartMOM uses internally, then shows how they differ from VLIDORT so you know exactly where to apply sign flips when comparing or importing data.
If you only read one section, read §4 — comparing against VLIDORT.
1. Stokes vector and reference plane
vSmartMOM uses the Stokes vector
So test/test_coxmunk_polarization.jl: an independent electric-field calculation reproduces vSmartMOM's own Rayleigh phase matrix only in this basis, and VLIDORT's complex-index Cox–Munk kernel fixes the sign of V. (Earlier versions of this page stated that
This is the Hovenier–van der Mee–Domke convention (Hovenier & van der Mee 1983; Hovenier, van der Mee & Domke 2004). The vSmartMOM theory papers print the Greek and generalized-spherical-function matrices in Siewert's form (§2); relative to that form, with Siewert's (2000) and VLIDORT's coefficient signs, the code's γ, ε, Q, U and V carry the opposite sign (§2, §4).
The polarization-type variants Stokes_I, Stokes_IQ, Stokes_IQU, Stokes_IQUV simply truncate this vector — they don't change the sign convention. (The RT solvers reject Stokes_IQ; it remains available in StandaloneSS ExactSSConfig runs and the Scattering-level functions.)
2. Phase matrix and Greek coefficients
The single-scattering phase matrix in vSmartMOM is expanded in generalized spherical functions following Siewert (1981, 2000) and de Rooij & van der Stap (1984). Sanghavi & Stephens (2015, Eqs. 21–22) print the Greek matrix and the generalized spherical-function matrix in Siewert's form, and the vSmartMOM paper (Sanghavi et al. 2014) uses Siewert's (1982) matrices by reference:
⎡ β_l γ_l 0 0 ⎤ ⎡ P_l^m 0 0 0 ⎤
B_l = ⎢ γ_l α_l 0 0 ⎥ , Π_l^m ∝ ⎢ 0 R_l^m −T_l^m 0 ⎥
⎢ 0 0 ζ_l −ε_l ⎥ ⎢ 0 −T_l^m R_l^m 0 ⎥
⎣ 0 0 ε_l δ_l ⎦ ⎣ 0 0 0 P_l^m ⎦with
How the code relates to the papers. vSmartMOM's construct_Π_matrix builds exactly the Π_l^m above. Its Stokes vector, however, is B_l \to D B_l D$, which changes the sign of the$[1,2]/[2,1]$elements and leaves the$[3,4]/[4,3]elements unchanged.construct_B_matrix(in src/Scattering/mie_helper_functions.jl) writes
⎡ β_l γ_l 0 0 ⎤
B_l,code = ⎢ γ_l α_l 0 0 ⎥ with γ_l(code) = −γ_l(Siewert),
⎢ 0 0 ζ_l ε_l ⎥ ε_l(code) = −ε_l(Siewert),
⎣ 0 0 −ε_l δ_l ⎦so its GreekCoefs.γ and GreekCoefs.ϵ (see src/Scattering/types.jl) are therefore Siewert's coefficients with the opposite sign. Importing coefficients in Siewert's (2000) or VLIDORT's convention negates both (§4); coefficients from vSmartMOM's own Mie code (NAI2/PCW, de Rooij & van der Stap 1984 definitions) are already in the code's convention.
The off-diagonal
Sign convention for get_greek_rayleigh returns
γ[L=2] = +√(3/2) · dpl_p # Hovenier-positivewith dpl_p = (1 − δ)/(1 + δ/2). This is consistent with vSmartMOM's own Mie code (_nai2_bulk_optics in compute_NAI2.jl, where f₁₂ = −Re(|s1|² − |s2|²)), so the entire vSmartMOM internal pipeline is self-consistent in Hovenier convention.
3. Azimuth angle (Δφ)
vSmartMOM defines the relative azimuth
Δφ = 0° ⇔ sun directly behind the satellite (forward scattering)
Δφ = 180° ⇔ sun and satellite on opposite sides of the
zenith within the principal plane (back scattering)The Fourier reconstruction in src/CoreRT/tools/postprocessing_vza.jl weights
For a mirror-symmetric atmosphere and surface with unpolarized illumination, at
4. Comparing against VLIDORT (and other codes)
VLIDORT (Spurr 2006, 2008; the V2.8.x series and PyVLIDORT) uses a partially different convention set. The differences that matter when cross-validating are summarised below.
4.1 Greek coefficients — γ at L=2
| Quantity | vSmartMOM (Hovenier) | VLIDORT (Mishchenko-style) |
|---|---|---|
| Rayleigh γ[L=2] | ||
Aerosol γ[L=2..N] from PROBLEM_IIA(3,:) / PROBLEMIII_b1 | sign-flip on import | as-is in data file |
When importing aerosol Greek coefficients from VLIDORT-format data files (Siewert 2000 PROBLEM_IIA(3,:), VLIDORT solar_tester PROBLEMIII_b1), flip the sign of γ on the way in so the imported aerosol γ is in vSmartMOM's Hovenier convention and matches the internally-generated Rayleigh γ. Otherwise the mixed-layerZ matrix accumulates from inconsistent signs.
ε from PROBLEM_IIA(5,:) / PROBLEMIII_b2 also needs a sign flip (GREEKMAT(:,12) = -PROBLEM_IIA(5,:) in the VLIDORT driver. This is widely-known and documented in the existing test reference files.
4.2 Stokes Q, U, V signs
For the VLIDORT reference drivers and saved tables used by this repository, the validated comparison applies opposite signs to Q, U, and V. This is a contract for those fixtures; check the full phase-matrix and reference-plane definitions before applying it to another driver or dataset.
When validating against a VLIDORT-format truth (e.g. results_solar_tester_IQU0.all, results_Siewert2000_validation.all), flip the sign of truth Q, U, and V before computing residuals:
truth_Q_compare = -truth_Q_vlidort
truth_U_compare = -truth_U_vlidort
truth_V_compare = -truth_V_vlidortWhy all three flip together: the I↔Q coupling (γ) propagates through the multi-scatter Mueller matrix to Q↔U (via α) and to V (via ε), so a single γ-sign flip cascades to every linear-polarization component. Confirmed empirically in Case A (Siewert 2000): with the symmetric flip all four Stokes components agree to the level quoted in §4.4.
4.3 Azimuth (RAZ) — same convention
vSmartMOM and VLIDORT use the same Δφ convention (forward at 0°, back at 180°), confirmed by Sanghavi (2026). Some other atmospheric RT codes use the opposite labeling — be aware of this if you import data from a non-VLIDORT source.
4.4 Worked example: Case A in the test suite
The cross-validation test/vlidort_baseline/cases/case_A_siewert2000.jl runs Siewert 2000 PROBLEM_IIA against VLIDORT 2.8.3 saved_results. Applying:
γ and ε sign-flips on import (
SIEWERT_γ = .-SIEWERT_PROBLEM_IIA.row3, and likewise ε from row 5)Truth Q/U/V sign-flip at comparison (
truth = -truthfor Q, U, V)
vSmartMOM matches VLIDORT to 7.7e-5 (I) and ≤ 3.3e-4 (Q, U, V) max relative error across all 3 azimuths (0°, 90°, 180°) and all 11 viewing zenith angles (test tolerances 5e-4 for I, U, V and 1e-2 for Q). This is the empirical validation of the convention story above.
5. Quick reference: import/export checklist
When importing greek coefficients from a VLIDORT-format file (Siewert 2000, PROBLEMIII, …):
| Field | Action on import |
|---|---|
| α (a2 / row1) | as-is |
| β (a1 / row2) | as-is |
| γ (b1 / row3) | flip sign (Mishchenko → Hovenier) |
| δ (a4 / row4) | as-is |
| ε (b2 / row5) | flip sign (B[3,4] storage convention) |
| ζ (a3 / row6) | as-is |
When comparing vSmartMOM output Stokes against a VLIDORT-format truth table:
| Stokes | Action on truth side |
|---|---|
| I | as-is |
| Q | flip sign |
| U | flip sign |
| V | flip sign |
When the Greek coefficients come from vSmartMOM's own Mie code (NAI2/PCW) or follow the same de Rooij & van der Stap (1984) definitions with this page's Stokes convention, no flips are needed. Coefficients in Siewert's or VLIDORT's convention (the form in which the vSmartMOM theory papers print
6. Quadrature streams and the direct solar direction
Two diffuse-grid counts and one phase-evaluation grid live on QuadPoints. Keeping them distinct prevents both stream-resolution mismatches and the accidental treatment of the collimated Sun as diffuse radiation.
Nstreams— count of nonzero weights (count(!iszero, wt_μ)). This is the user-facing resolving-power knob. The public contract isstream_l_cap = 2·Nstreams - 1i.e., the largest Legendre order the chosen quadrature is contracted to resolve. Set
radiative_transfer.nstreams = Nin YAML; the engine guarantees2·N - 1resolving order regardless of which quadrature scheme is chosen.Nquad— total node count in the square diffuse operator. It includes the weighted streams and any distinct zero-weight viewing nodes; the default embedded- Gauss representation also includes the distinct SZA. It sets the matrix workspace sizeNquadN = Nquad · n_stokes.phase_qp_μ— directions used to evaluate phase matrices. It is identical toqp_μin the default embedded- representation. In the opt-in external-solar SFI, it additionally records exact as compatibility metadata. Production source kernels evaluate rectangular columns directly and do not index as an operator node.
Per-scheme construction
| Scheme | Weighted-streams construction | Solar treatment |
|---|---|---|
GaussLegQuad with external_solar=true (opt-in, TOA-only) | Gauss-Legendre on [0, 1], (Ltrunc+2)÷2 nodes (Sanghavi: +2 form avoids zero streams at Ltrunc=0) | Only VZAs are appended to the operator; scalar |
GaussLegQuad (default, external_solar=false) | Same weighted Gauss nodes | SZA and VZAs are appended as zero-weight operator nodes. |
RadauQuad | Gauss-Radau on subintervals around μ₀; the SZA-on-node branch builds (Ltrunc+1)÷2 nodes, while the usual SZA-not-on-node branch builds 2·((Ltrunc+1)÷2) weighted nodes split around μ₀ (coincident nodes of a near-overhead sun are merged, summing their weights) |
Because Radau allocates a different number of weighted nodes depending on whether μ₀ lands on a Gauss-Radau abscissa, the Nstreams field is computed as count(!iszero, wt_μ) rather than a formula — this guarantees it matches what the builder actually produced. Radau's split-around-μ₀ branch typically uses more weighted streams than Gauss for the same Ltrunc, which is one reason Radau is more expensive; Sanghavi recommends GaussLegQuad as the default. Radau remains available for users who need an SZA-on-node quadrature but is documented as expert/legacy.
Appended ordinates (VZAs and, when embedded, μ₀) that lie within 4·eps(1) of a node already on the grid are merged into that node rather than added as a numerically coincident second ordinate, and a node that close to μ₀ is moved onto the exact μ₀ (keeping its weight). A cosine one rounding error from a node (for example sza = acosd(node)) therefore gives the on-node result; grids without such a near-coincidence are unchanged. Outside this window the elemental kernels stay accurate however close two ordinates are: they evaluate the elem_trans_factor; The MOM Solver). This also covers Radau's own weighted sub-interval nodes for a near-overhead sun, which can lie a few ulps apart and are merged only when exactly equal.
All representations report:
qp.Nstreams= weighted streams (resolving power)qp.Nquad= diffuse-operator total (kernel size)qp.wt_μcarries explicit zeros at appended viewing directions and, in the default embedded- Gauss mode, at SZAqp.μ₀supplies the exact external-solar propagation direction;phase_qp_μ/iμ₀_phaseremain compatibility metadata for the embedded path
The RTModel Base.show summary prints both: "Nstreams=N, Nquad=M".
External-solar SFI and the 18×18 exoplanet operator
Embedded-external_solar=false) is the model-construction default — it supports every entry point (full R, T, observer heights, the atmosphere/surface split). external_solar=true is the opt-in TOA-only fast path consumed through rt_run_toa. In external mode, iμ₀ and iμ₀Nstart are therefore zero sentinels; source coupling uses iμ₀_phase.
For five weighted Gauss streams, one distinct VZA, and Stokes_IQU, the diffuse operator dimension is
(5 weighted + 1 VZA) · 3 Stokes = 18,so adding/doubling works on
The external-solar implementation is deliberately narrow at present:
GaussLegQuad, source-function integration, elastic forward/linearizednoRS, forward rotational RamanRRS, and Lambertian surfaces;no Raman Jacobian, VRS, single-scatter-only, non-Lambertian, or interior sensor path;
call
rt_run_toa(model)for elastic orrt_run_toa(rs, model)for RRS; these return only directional upwelling TOA Stokes radiance. It does not allocate or postprocess BOA, HDR, or BHR products. Atmospheric multiple scattering and surface reflection are still solved because both contribute to TOA radiance.
7. Where this lives in code
| Concept | File |
|---|---|
| B-matrix construction (storage convention, §2) | src/Scattering/mie_helper_functions.jl (construct_B_matrix) |
| Rayleigh γ (Hovenier-positive) | src/Scattering/mie_helper_functions.jl (get_greek_rayleigh) |
| Mie coefficient sign (compute_NAI2 f₁₂) | src/Scattering/compute_NAI2.jl |
| Azimuth weighting (sin/cos by Stokes) | src/CoreRT/tools/postprocessing_vza.jl |
| VLIDORT cross-validation (worked example) | test/vlidort_baseline/ |
References
de Rooij, W.A. & van der Stap, C.C.A.H. (1984). Expansion of Mie scattering matrices in generalized spherical functions. A&A 131, 237.
de Haan, J.F., Bosma, P.B. & Hovenier, J.W. (1987). The adding method for multiple scattering calculations of polarized light. A&A 183, 371.
Hovenier, J.W., van der Mee, C., & Domke, H. (2004). Transfer of Polarized Light in Planetary Atmospheres — Basic Concepts and Practical Methods. Springer / Kluwer.
Mishchenko, M.I., Travis, L.D., & Lacis, A.A. (2002). Scattering, Absorption, and Emission of Light by Small Particles. CUP.
Natraj, V., Hovenier, J.W. (2012). Polarized light reflected and transmitted by thick Rayleigh scattering atmospheres. ApJ 748, 28.
Sanghavi, S., Davis, A.B. & Eldering, A. (2014). vSmartMOM: A vector matrix operator method-based radiative transfer model linearized with respect to aerosol properties. JQSRT 133, 412–433.
Sanghavi, S. (2014). Revisiting the Fourier expansion of Mie scattering matrices in generalized spherical functions. JQSRT 136, 16–27.
Sanghavi, S. & Stephens, G. (2015). Adaptation of the delta-m and δ-fit truncation methods to vector radiative transfer: Effect of truncation on radiative transfer accuracy. JQSRT 159, 53–68.
Siewert, C.E. (1981). On the equation of transfer relevant to the scattering of polarized light. Astrophys. J. 245, 1080–1086.
Siewert, C.E. (1982). On the phase matrix basic to the scattering of polarized light. A&A 109, 195–200.
Siewert, C.E. (2000). A discrete-ordinates solution for radiative transfer models that include polarization effects. JQSRT 64, 227–254.
Spurr, R.J.D. (2006). VLIDORT: A linearized pseudo-spherical vector discrete ordinate radiative transfer code... JQSRT 102, 316.