Version: dev

MieScattering

Mie theory scattering and extinction efficiencies, cross sections, and mass efficiencies for a spherical particle, from Seinfeld & Pandis (2006), Atmospheric Chemistry and Physics, 2nd ed., Chapter 15, Eqs. 15.3–15.6, 15.41–15.43. The size parameter α = π D_p / λ is algebraic; Q_ext and Q_scat (computed upstream by the Bohren–Huffman algorithm via @register_symbolic Mie functions, ESS gap gt-p3ep) are lifted to input parameters with Mie-computed defaults at D_p = 0.5 µm, λ = 550 nm, n_refr = 1.5, k_refr = 0. Q_abs, ω, the three cross sections (C_scat, C_abs, C_ext), and the three mass efficiencies (E_scat, E_abs, E_ext) are algebraic outputs. Migrated from Aerosol.jl MieScattering.

Domain
aerosol
Subdomain
mie
Type
model
.esm schema
1.0.0
Source
components/aerosol/mie/mie_scattering.esm
Tags
#aerosol #mie #model #optical #scattering #extinction #seinfeld_pandis_ch15

Description

Mie theory scattering and extinction efficiencies, cross sections, and mass efficiencies for a spherical particle, from Seinfeld & Pandis (2006), Atmospheric Chemistry and Physics, 2nd ed., Chapter 15, Eqs. 15.3–15.6, 15.41–15.43. The size parameter α = π D_p / λ is algebraic; Q_ext and Q_scat (computed upstream by the Bohren–Huffman algorithm via @register_symbolic Mie functions, ESS gap gt-p3ep) are lifted to input parameters with Mie-computed defaults at D_p = 0.5 µm, λ = 550 nm, n_refr = 1.5, k_refr = 0. Q_abs, ω, the three cross sections (C_scat, C_abs, C_ext), and the three mass efficiencies (E_scat, E_abs, E_ext) are algebraic outputs. Migrated from Aerosol.jl MieScattering.

Reference

_source_ref: Aerosol.jl@c8c640bb636b22f2425460e9ed5cba50793bfee1:src/mie_scattering.jl:36

Upstream MieScattering is an MTK @component with one @constants (π_val = Float64(π)), five @parameters (D_p, λ, n_refr, k_refr, ρ_p), and eleven time-indexed @variables (α, Q_scat, Q_abs, Q_ext, ω, C_scat, C_abs, C_ext, E_scat, E_abs, E_ext). The eleven equations are: • α ~ π_val * D_p / λ (Eq. 15.6, size parameter) • Q_ext ~ mie_Q_ext(α, n_refr, k_refr) (@register_symbolic Mie function, Eq. 15.14) • Q_scat ~ mie_Q_scat(α, n_refr, k_refr) (@register_symbolic Mie function, Eq. 15.13) • Q_abs ~ Q_ext - Q_scat (Eq. 15.4) • ω ~ Q_scat / Q_ext (Eq. 15.5) • C_scat ~ Q_scat * π_val * D_p^2 / 4 • C_abs ~ Q_abs * π_val * D_p^2 / 4 • C_ext ~ Q_ext * π_val * D_p^2 / 4 (Eq. 15.3 implied) • E_ext ~ 3 * Q_ext / (2 * ρ_p * D_p) (Eq. 15.41) • E_scat ~ 3 * Q_scat / (2 * ρ_p * D_p) (Eq. 15.42) • E_abs ~ 3 * Q_abs / (2 * ρ_p * D_p) (Eq. 15.43)

gt-p3ep resolution: Q_ext and Q_scat are computed upstream by the Bohren–Huffman Mie algorithm via @register_symbolic functions (mie_Q_ext, mie_Q_scat). These cannot be expressed as algebraic AST compositions in the ESS schema. The migration resolves this by lifting Q_ext and Q_scat to input type: parameter fields with default values taken from the Mie calculation at the upstream default parameter values (D_p = 0.5e-6 m, λ = 550e-9 m, n_refr = 1.5, k_refr = 0, α = π×0.5e-6/550e-9 ≈ 2.856): Q_ext = 8.136639625628797, Q_scat = 8.136639625628797. This is the same lifting strategy applied to AerosolExtinction (esm-nyn), which depends on the same Mie functions.

Unused-parameter pruning: n_refr and k_refr (refractive index real and imaginary parts) appear only in the Mie function calls mie_Q_ext and mie_Q_scat, which are replaced by the lifted parameters Q_ext and Q_scat. After lifting, n_refr and k_refr do not appear in any remaining algebraic equation and are therefore omitted per the unused-parameter rule.

@constants handling: π_val (Float64(π) = 3.141592653589793) is an upstream @constants entry. The ESS schema has no constant variable type; it migrates as type: parameter with a fixed numeric default, consistent with the rig-wide convention (e.g., π_val in AerosolExtinction esm-nyn).

ρ_p is retained: it appears in the three mass efficiency equations (E_ext, E_scat, E_abs) and is NOT pruned.

Observed-only classification: the component is purely algebraic — no D() time-derivatives appear. After lifting Q_ext and Q_scat to parameters, the remaining nine computed quantities (α, Q_abs, ω, C_scat, C_abs, C_ext, E_ext, E_scat, E_abs) are each defined by one algebraic relation and are serialized as type: observed with an expression; the equations array is empty.

Tests: the upstream mie_scattering_test.jl verifies structural properties and Mie function behaviour, not the derived quantities here. The inline tests block is authored from the algebraic equations themselves. The default-parameters test pins all nine observed outputs at the upstream defaults; Q_abs = 0 and ω = 1 because k_refr = 0 (non-absorbing); C_abs = 0 and E_abs = 0 likewise. The absorbing-particle test (Q_ext = 3.0, Q_scat = 2.5) verifies the absorption branch for all nine outputs. The size-parameter test checks α = π D_p / λ at a different (D_p, λ). The density-scaling test varies ρ_p and confirms the 1/ρ_p linear scaling in the mass efficiencies.

Tolerance rationale (model-level rel=1e-9): purely algebraic — each observed output is a chain of +, -, *, /, ^ over float64 parameters. Float64 round-off is ~1e-15; rel=1e-9 leaves six orders of magnitude of headroom and absorbs any associativity difference in multi-factor products._

Parameters

NameUnitsDefaultDescription
π_val13.141592653589793Pi (dimensionless). Upstream MTK @constants entry π_val = Float64(π); migrated as a fixed-default parameter.
D_pm5e-07Particle diameter. Default 0.5 µm (0.5e-6 m) — the upstream default.
λm5.5e-07Wavelength of incident radiation. Default 550 nm (550e-9 m) — visible green light, the upstream default.
ρ_pkg/m^31500.0Particle density. Default 1500 kg/m³ — the upstream default. Appears in mass efficiency equations E_ext, E_scat, E_abs.
Q_ext18.136639625628797Extinction efficiency (dimensionless). Upstream MTK variable; lifted to parameter because the defining equation Q_ext ~ mie_Q_ext(α, n_refr, k_refr) uses a @register_symbolic Mie function (Bohren–Huffman algorithm) that cannot be expressed in the ESS algebraic AST (gt-p3ep). Default is the Mie solution at D_p = 0.5e-6 m, λ = 550e-9 m, n_refr = 1.5, k_refr = 0 (size parameter α ≈ 2.856).
Q_scat18.136639625628797Scattering efficiency (dimensionless). Upstream MTK variable; lifted to parameter because the defining equation Q_scat ~ mie_Q_scat(α, n_refr, k_refr) uses a @register_symbolic Mie function that cannot be expressed in the ESS algebraic AST (gt-p3ep). Default equals Q_ext because k_refr = 0 (non-absorbing) at the upstream defaults.

Observed

NameUnitsDefaultDescription
α1Size parameter α = π D_p / λ (dimensionless). Ratio of particle circumference to wavelength; drives the transition from Rayleigh (α « 1) to geometric optics (α » 1) regimes (Seinfeld & Pandis 2006, Eq. 15.6). Preserved as an algebraic observed for reference even though it formerly served as an argument to the removed Mie function calls.
Q_abs1Absorption efficiency Q_abs = Q_ext - Q_scat (dimensionless). Non-negative; equals zero for non-absorbing particles (k_refr = 0, i.e., purely real refractive index) (Seinfeld & Pandis 2006, Eq. 15.4).
ω1Single-scattering albedo ω = Q_scat / Q_ext (dimensionless). Fraction of total extinction due to scattering rather than absorption; ranges from 0 (pure absorber) to 1 (pure scatterer). Equal to 1 for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.5).
C_scatm^2Scattering cross section C_scat = Q_scat (π/4) D_p² (m²). Effective area that scatters incident radiation; proportional to the geometric cross section (π/4)D_p² scaled by Q_scat (Seinfeld & Pandis 2006, Eq. 15.37 implied).
C_absm^2Absorption cross section C_abs = Q_abs (π/4) D_p² (m²). Effective area that absorbs incident radiation; zero for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.38 implied).
C_extm^2Extinction cross section C_ext = Q_ext (π/4) D_p² (m²). Total effective area that removes incident radiation by scattering plus absorption; C_ext = C_scat + C_abs (Seinfeld & Pandis 2006, Eq. 15.3 implied, Eq. 15.39 implied).
E_extm^2/kgMass extinction efficiency E_ext = 3 Q_ext / (2 ρ_p D_p) (m²/kg). Extinction cross section per unit mass; scales as 1/(ρ_p D_p), so smaller and denser particles are less efficient per unit mass (Seinfeld & Pandis 2006, Eq. 15.41).
E_scatm^2/kgMass scattering efficiency E_scat = 3 Q_scat / (2 ρ_p D_p) (m²/kg). Scattering cross section per unit mass (Seinfeld & Pandis 2006, Eq. 15.42).
E_absm^2/kgMass absorption efficiency E_abs = 3 Q_abs / (2 ρ_p D_p) (m²/kg). Absorption cross section per unit mass; zero for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.43).

Observed expressions

$$ α = \frac{π_{val} \cdot D_{p}}{λ} $$

Size parameter α = π D_p / λ (dimensionless). Ratio of particle circumference to wavelength; drives the transition from Rayleigh (α « 1) to geometric optics (α » 1) regimes (Seinfeld & Pandis 2006, Eq. 15.6). Preserved as an algebraic observed for reference even though it formerly served as an argument to the removed Mie function calls.

$$ Q_{abs} = Q_{ext} - Q_{scat} $$

Absorption efficiency Q_abs = Q_ext - Q_scat (dimensionless). Non-negative; equals zero for non-absorbing particles (k_refr = 0, i.e., purely real refractive index) (Seinfeld & Pandis 2006, Eq. 15.4).

$$ ω = \frac{Q_{scat}}{Q_{ext}} $$

Single-scattering albedo ω = Q_scat / Q_ext (dimensionless). Fraction of total extinction due to scattering rather than absorption; ranges from 0 (pure absorber) to 1 (pure scatterer). Equal to 1 for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.5).

$$ C_{scat} = \frac{Q_{scat} \cdot π_{val} \cdot D_{p}^{2}}{4} $$

Scattering cross section C_scat = Q_scat (π/4) D_p² (m²). Effective area that scatters incident radiation; proportional to the geometric cross section (π/4)D_p² scaled by Q_scat (Seinfeld & Pandis 2006, Eq. 15.37 implied).

$$ C_{abs} = \frac{Q_{abs} \cdot π_{val} \cdot D_{p}^{2}}{4} $$

Absorption cross section C_abs = Q_abs (π/4) D_p² (m²). Effective area that absorbs incident radiation; zero for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.38 implied).

$$ C_{ext} = \frac{Q_{ext} \cdot π_{val} \cdot D_{p}^{2}}{4} $$

Extinction cross section C_ext = Q_ext (π/4) D_p² (m²). Total effective area that removes incident radiation by scattering plus absorption; C_ext = C_scat + C_abs (Seinfeld & Pandis 2006, Eq. 15.3 implied, Eq. 15.39 implied).

$$ E_{ext} = \frac{3 \cdot Q_{ext}}{2 \cdot ρ_{p} \cdot D_{p}} $$

Mass extinction efficiency E_ext = 3 Q_ext / (2 ρ_p D_p) (m²/kg). Extinction cross section per unit mass; scales as 1/(ρ_p D_p), so smaller and denser particles are less efficient per unit mass (Seinfeld & Pandis 2006, Eq. 15.41).

$$ E_{scat} = \frac{3 \cdot Q_{scat}}{2 \cdot ρ_{p} \cdot D_{p}} $$

Mass scattering efficiency E_scat = 3 Q_scat / (2 ρ_p D_p) (m²/kg). Scattering cross section per unit mass (Seinfeld & Pandis 2006, Eq. 15.42).

$$ E_{abs} = \frac{3 \cdot Q_{abs}}{2 \cdot ρ_{p} \cdot D_{p}} $$

Mass absorption efficiency E_abs = 3 Q_abs / (2 ρ_p D_p) (m²/kg). Absorption cross section per unit mass; zero for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.43).

Raw .esm

Raw .esm JSON (this component)
{
  "reference": {
    "notes": "source_ref: Aerosol.jl@c8c640bb636b22f2425460e9ed5cba50793bfee1:src/mie_scattering.jl:36\n\nUpstream `MieScattering` is an MTK `@component` with one `@constants` (π_val = Float64(π)), five `@parameters` (D_p, λ, n_refr, k_refr, ρ_p), and eleven time-indexed `@variables` (α, Q_scat, Q_abs, Q_ext, ω, C_scat, C_abs, C_ext, E_scat, E_abs, E_ext). The eleven equations are:\n  • α ~ π_val * D_p / λ  (Eq. 15.6, size parameter)\n  • Q_ext ~ mie_Q_ext(α, n_refr, k_refr)  (@register_symbolic Mie function, Eq. 15.14)\n  • Q_scat ~ mie_Q_scat(α, n_refr, k_refr)  (@register_symbolic Mie function, Eq. 15.13)\n  • Q_abs ~ Q_ext - Q_scat  (Eq. 15.4)\n  • ω ~ Q_scat / Q_ext  (Eq. 15.5)\n  • C_scat ~ Q_scat * π_val * D_p^2 / 4\n  • C_abs ~ Q_abs * π_val * D_p^2 / 4\n  • C_ext ~ Q_ext * π_val * D_p^2 / 4  (Eq. 15.3 implied)\n  • E_ext ~ 3 * Q_ext / (2 * ρ_p * D_p)  (Eq. 15.41)\n  • E_scat ~ 3 * Q_scat / (2 * ρ_p * D_p)  (Eq. 15.42)\n  • E_abs ~ 3 * Q_abs / (2 * ρ_p * D_p)  (Eq. 15.43)\n\ngt-p3ep resolution: Q_ext and Q_scat are computed upstream by the Bohren–Huffman Mie algorithm via @register_symbolic functions (mie_Q_ext, mie_Q_scat). These cannot be expressed as algebraic AST compositions in the ESS schema. The migration resolves this by lifting Q_ext and Q_scat to input `type: parameter` fields with default values taken from the Mie calculation at the upstream default parameter values (D_p = 0.5e-6 m, λ = 550e-9 m, n_refr = 1.5, k_refr = 0, α = π×0.5e-6/550e-9 ≈ 2.856): Q_ext = 8.136639625628797, Q_scat = 8.136639625628797. This is the same lifting strategy applied to AerosolExtinction (esm-nyn), which depends on the same Mie functions.\n\nUnused-parameter pruning: n_refr and k_refr (refractive index real and imaginary parts) appear only in the Mie function calls mie_Q_ext and mie_Q_scat, which are replaced by the lifted parameters Q_ext and Q_scat. After lifting, n_refr and k_refr do not appear in any remaining algebraic equation and are therefore omitted per the unused-parameter rule.\n\n@constants handling: π_val (Float64(π) = 3.141592653589793) is an upstream `@constants` entry. The ESS schema has no constant variable type; it migrates as `type: parameter` with a fixed numeric default, consistent with the rig-wide convention (e.g., π_val in AerosolExtinction esm-nyn).\n\nρ_p is retained: it appears in the three mass efficiency equations (E_ext, E_scat, E_abs) and is NOT pruned.\n\nObserved-only classification: the component is purely algebraic — no D() time-derivatives appear. After lifting Q_ext and Q_scat to parameters, the remaining nine computed quantities (α, Q_abs, ω, C_scat, C_abs, C_ext, E_ext, E_scat, E_abs) are each defined by one algebraic relation and are serialized as `type: observed` with an `expression`; the `equations` array is empty.\n\nTests: the upstream mie_scattering_test.jl verifies structural properties and Mie function behaviour, not the derived quantities here. The inline `tests` block is authored from the algebraic equations themselves. The default-parameters test pins all nine observed outputs at the upstream defaults; Q_abs = 0 and ω = 1 because k_refr = 0 (non-absorbing); C_abs = 0 and E_abs = 0 likewise. The absorbing-particle test (Q_ext = 3.0, Q_scat = 2.5) verifies the absorption branch for all nine outputs. The size-parameter test checks α = π D_p / λ at a different (D_p, λ). The density-scaling test varies ρ_p and confirms the 1/ρ_p linear scaling in the mass efficiencies.\n\nTolerance rationale (model-level rel=1e-9): purely algebraic — each observed output is a chain of +, -, *, /, ^ over float64 parameters. Float64 round-off is ~1e-15; rel=1e-9 leaves six orders of magnitude of headroom and absorbs any associativity difference in multi-factor products."
  },
  "tolerance": {
    "rel": 1e-09
  },
  "variables": {
    "π_val": {
      "type": "parameter",
      "units": "1",
      "default": 3.141592653589793,
      "description": "Pi (dimensionless). Upstream MTK @constants entry π_val = Float64(π); migrated as a fixed-default parameter."
    },
    "D_p": {
      "type": "parameter",
      "units": "m",
      "default": 5e-07,
      "description": "Particle diameter. Default 0.5 µm (0.5e-6 m) — the upstream default."
    },
    "λ": {
      "type": "parameter",
      "units": "m",
      "default": 5.5e-07,
      "description": "Wavelength of incident radiation. Default 550 nm (550e-9 m) — visible green light, the upstream default."
    },
    "ρ_p": {
      "type": "parameter",
      "units": "kg/m^3",
      "default": 1500.0,
      "description": "Particle density. Default 1500 kg/m³ — the upstream default. Appears in mass efficiency equations E_ext, E_scat, E_abs."
    },
    "Q_ext": {
      "type": "parameter",
      "units": "1",
      "default": 8.136639625628797,
      "description": "Extinction efficiency (dimensionless). Upstream MTK variable; lifted to parameter because the defining equation Q_ext ~ mie_Q_ext(α, n_refr, k_refr) uses a @register_symbolic Mie function (Bohren–Huffman algorithm) that cannot be expressed in the ESS algebraic AST (gt-p3ep). Default is the Mie solution at D_p = 0.5e-6 m, λ = 550e-9 m, n_refr = 1.5, k_refr = 0 (size parameter α ≈ 2.856)."
    },
    "Q_scat": {
      "type": "parameter",
      "units": "1",
      "default": 8.136639625628797,
      "description": "Scattering efficiency (dimensionless). Upstream MTK variable; lifted to parameter because the defining equation Q_scat ~ mie_Q_scat(α, n_refr, k_refr) uses a @register_symbolic Mie function that cannot be expressed in the ESS algebraic AST (gt-p3ep). Default equals Q_ext because k_refr = 0 (non-absorbing) at the upstream defaults."
    },
    "α": {
      "type": "unknown",
      "units": "1",
      "description": "Size parameter α = π D_p / λ (dimensionless). Ratio of particle circumference to wavelength; drives the transition from Rayleigh (α << 1) to geometric optics (α >> 1) regimes (Seinfeld & Pandis 2006, Eq. 15.6). Preserved as an algebraic observed for reference even though it formerly served as an argument to the removed Mie function calls."
    },
    "Q_abs": {
      "type": "unknown",
      "units": "1",
      "description": "Absorption efficiency Q_abs = Q_ext - Q_scat (dimensionless). Non-negative; equals zero for non-absorbing particles (k_refr = 0, i.e., purely real refractive index) (Seinfeld & Pandis 2006, Eq. 15.4)."
    },
    "ω": {
      "type": "unknown",
      "units": "1",
      "description": "Single-scattering albedo ω = Q_scat / Q_ext (dimensionless). Fraction of total extinction due to scattering rather than absorption; ranges from 0 (pure absorber) to 1 (pure scatterer). Equal to 1 for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.5)."
    },
    "C_scat": {
      "type": "unknown",
      "units": "m^2",
      "description": "Scattering cross section C_scat = Q_scat (π/4) D_p² (m²). Effective area that scatters incident radiation; proportional to the geometric cross section (π/4)D_p² scaled by Q_scat (Seinfeld & Pandis 2006, Eq. 15.37 implied)."
    },
    "C_abs": {
      "type": "unknown",
      "units": "m^2",
      "description": "Absorption cross section C_abs = Q_abs (π/4) D_p² (m²). Effective area that absorbs incident radiation; zero for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.38 implied)."
    },
    "C_ext": {
      "type": "unknown",
      "units": "m^2",
      "description": "Extinction cross section C_ext = Q_ext (π/4) D_p² (m²). Total effective area that removes incident radiation by scattering plus absorption; C_ext = C_scat + C_abs (Seinfeld & Pandis 2006, Eq. 15.3 implied, Eq. 15.39 implied)."
    },
    "E_ext": {
      "type": "unknown",
      "units": "m^2/kg",
      "description": "Mass extinction efficiency E_ext = 3 Q_ext / (2 ρ_p D_p) (m²/kg). Extinction cross section per unit mass; scales as 1/(ρ_p D_p), so smaller and denser particles are less efficient per unit mass (Seinfeld & Pandis 2006, Eq. 15.41)."
    },
    "E_scat": {
      "type": "unknown",
      "units": "m^2/kg",
      "description": "Mass scattering efficiency E_scat = 3 Q_scat / (2 ρ_p D_p) (m²/kg). Scattering cross section per unit mass (Seinfeld & Pandis 2006, Eq. 15.42)."
    },
    "E_abs": {
      "type": "unknown",
      "units": "m^2/kg",
      "description": "Mass absorption efficiency E_abs = 3 Q_abs / (2 ρ_p D_p) (m²/kg). Absorption cross section per unit mass; zero for non-absorbing particles (Seinfeld & Pandis 2006, Eq. 15.43)."
    }
  },
  "equations": [
    {
      "lhs": "α",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              "π_val",
              "D_p"
            ]
          },
          "λ"
        ]
      }
    },
    {
      "lhs": "Q_abs",
      "rhs": {
        "op": "-",
        "args": [
          "Q_ext",
          "Q_scat"
        ]
      }
    },
    {
      "lhs": "ω",
      "rhs": {
        "op": "/",
        "args": [
          "Q_scat",
          "Q_ext"
        ]
      }
    },
    {
      "lhs": "C_scat",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              "Q_scat",
              "π_val",
              {
                "op": "^",
                "args": [
                  "D_p",
                  2
                ]
              }
            ]
          },
          4
        ]
      }
    },
    {
      "lhs": "C_abs",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              "Q_abs",
              "π_val",
              {
                "op": "^",
                "args": [
                  "D_p",
                  2
                ]
              }
            ]
          },
          4
        ]
      }
    },
    {
      "lhs": "C_ext",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              "Q_ext",
              "π_val",
              {
                "op": "^",
                "args": [
                  "D_p",
                  2
                ]
              }
            ]
          },
          4
        ]
      }
    },
    {
      "lhs": "E_ext",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              3,
              "Q_ext"
            ]
          },
          {
            "op": "*",
            "args": [
              2,
              "ρ_p",
              "D_p"
            ]
          }
        ]
      }
    },
    {
      "lhs": "E_scat",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              3,
              "Q_scat"
            ]
          },
          {
            "op": "*",
            "args": [
              2,
              "ρ_p",
              "D_p"
            ]
          }
        ]
      }
    },
    {
      "lhs": "E_abs",
      "rhs": {
        "op": "/",
        "args": [
          {
            "op": "*",
            "args": [
              3,
              "Q_abs"
            ]
          },
          {
            "op": "*",
            "args": [
              2,
              "ρ_p",
              "D_p"
            ]
          }
        ]
      }
    }
  ],
  "tests": [
    {
      "id": "default_params_all_outputs",
      "description": "All parameters at their declared defaults: D_p = 0.5e-6 m, λ = 550e-9 m, ρ_p = 1500 kg/m³, Q_ext = Q_scat = 8.136639625628797 (Mie solution at D_p = 0.5 µm, λ = 550 nm, n_refr = 1.5, k_refr = 0). Pins all nine observed outputs. α = π×0.5e-6/550e-9 ≈ 2.856. Q_abs = 0 and ω = 1 (non-absorbing, k_refr = 0). C_abs = 0. E_abs = 0. Cross sections and mass efficiencies at default Q_ext = Q_scat. All outputs are algebraic and time-independent; α and ω are asserted at t=1 as well to confirm time-invariance.",
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "α",
          "time": 0.0,
          "expected": 2.855993321445266
        },
        {
          "variable": "Q_abs",
          "time": 0.0,
          "expected": 0.0
        },
        {
          "variable": "ω",
          "time": 0.0,
          "expected": 1.0
        },
        {
          "variable": "C_scat",
          "time": 0.0,
          "expected": 1.5976254545489396e-12
        },
        {
          "variable": "C_abs",
          "time": 0.0,
          "expected": 0.0
        },
        {
          "variable": "C_ext",
          "time": 0.0,
          "expected": 1.5976254545489396e-12
        },
        {
          "variable": "E_ext",
          "time": 0.0,
          "expected": 16273.279251257594
        },
        {
          "variable": "E_scat",
          "time": 0.0,
          "expected": 16273.279251257594
        },
        {
          "variable": "E_abs",
          "time": 0.0,
          "expected": 0.0
        },
        {
          "variable": "α",
          "time": 1.0,
          "expected": 2.855993321445266
        },
        {
          "variable": "ω",
          "time": 1.0,
          "expected": 1.0
        }
      ]
    },
    {
      "id": "absorbing_particle",
      "description": "Absorbing aerosol: Q_ext = 3.0, Q_scat = 2.5 → Q_abs = 0.5, ω = Q_scat/Q_ext = 5/6 ≈ 0.8333. Verifies the absorption branch for all outputs. At D_p = 0.5e-6 m the geometric factor (π/4)D_p² = π×(0.5e-6)²/4 ≈ 1.9635e-13 m². C_scat = 2.5×1.9635e-13 ≈ 4.909e-13. C_abs = 0.5×1.9635e-13 ≈ 9.817e-14. C_ext = 3.0×1.9635e-13 ≈ 5.890e-13. Mass efficiencies scale with Q and divide by 2×1500×0.5e-6 = 1.5e-3: E_ext = 9/1.5e-3 = 6000, E_scat = 7.5/1.5e-3 = 5000, E_abs = 1.5/1.5e-3 = 1000.",
      "parameter_overrides": {
        "Q_ext": 3.0,
        "Q_scat": 2.5
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "Q_abs",
          "time": 0.0,
          "expected": 0.5
        },
        {
          "variable": "ω",
          "time": 0.0,
          "expected": 0.8333333333333334
        },
        {
          "variable": "C_scat",
          "time": 0.0,
          "expected": 4.908738521234051e-13
        },
        {
          "variable": "C_abs",
          "time": 0.0,
          "expected": 9.817477042468102e-14
        },
        {
          "variable": "C_ext",
          "time": 0.0,
          "expected": 5.890486225480862e-13
        },
        {
          "variable": "E_ext",
          "time": 0.0,
          "expected": 6000.0
        },
        {
          "variable": "E_scat",
          "time": 0.0,
          "expected": 5000.0
        },
        {
          "variable": "E_abs",
          "time": 0.0,
          "expected": 1000.0
        }
      ]
    },
    {
      "id": "size_parameter_ratio",
      "description": "Size parameter α = π D_p / λ at D_p = 1e-6 m (1 µm) and λ = 500e-9 m (500 nm): α = π × 1e-6 / 500e-9 = 2π ≈ 6.283. Tests the Eq. 15.6 formula independently of the lifted Mie efficiencies.",
      "parameter_overrides": {
        "D_p": 1e-06,
        "λ": 5e-07
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "α",
          "time": 0.0,
          "expected": 6.283185307179586
        }
      ]
    },
    {
      "id": "density_scaling_mass_efficiencies",
      "description": "Mass efficiencies scale as 1/ρ_p. With ρ_p = 2000 kg/m³ (vs default 1500), D_p = 1e-6 m, Q_ext = 3.0, Q_scat = 2.5 (Q_abs = 0.5): denominator = 2×2000×1e-6 = 4e-3. E_ext = 9/4e-3 = 2250, E_scat = 7.5/4e-3 = 1875, E_abs = 1.5/4e-3 = 375. Cross sections at D_p = 1e-6: geometric factor = π×(1e-6)²/4 ≈ 7.854e-13. C_scat = 2.5×7.854e-13 ≈ 1.963e-12, C_ext = 3.0×7.854e-13 ≈ 2.356e-12, C_abs = 0.5×7.854e-13 ≈ 3.927e-13.",
      "parameter_overrides": {
        "D_p": 1e-06,
        "ρ_p": 2000.0,
        "Q_ext": 3.0,
        "Q_scat": 2.5
      },
      "time_span": {
        "start": 0.0,
        "end": 1.0
      },
      "assertions": [
        {
          "variable": "E_ext",
          "time": 0.0,
          "expected": 2250.0
        },
        {
          "variable": "E_scat",
          "time": 0.0,
          "expected": 1875.0
        },
        {
          "variable": "E_abs",
          "time": 0.0,
          "expected": 375.0
        },
        {
          "variable": "C_scat",
          "time": 0.0,
          "expected": 1.9634954084936206e-12
        },
        {
          "variable": "C_ext",
          "time": 0.0,
          "expected": 2.356194490192345e-12
        },
        {
          "variable": "C_abs",
          "time": 0.0,
          "expected": 3.926990816987242e-13
        }
      ]
    }
  ]
}