This notebook teaches the physics of radiative transfer in snow and ice from first principles — starting with Maxwell's equations and building up, layer by layer, to the complete adding-doubling solver implemented in BioSNICAR.
| Act | Theme | Sections | Core question |
|---|---|---|---|
| I | From Maxwell to Mie | 1 – 4 | How does light interact with a single ice grain? |
| II | Single Particles → Bulk Properties | 5 – 8 | How do many grains create a scattering medium? |
| III | The Radiative Transfer Equation | 9 – 13 | How does light propagate through a layered snowpack? |
| IV | Light-Absorbing Particles | 14 – 18 | How do impurities darken the surface? |
| V | The Complete BioSNICAR Solver | 19 – 22 | How does BioSNICAR assemble all the pieces? |
| VI | Putting It All Together | 23 – 25 | Sensitivity, demonstrations, and summary |
.ipynb filegit clone https://github.com/jmcook1186/biosnicar-py.git && cd biosnicar-py/notebooks && jupyter notebook radiative_transfer_fundamentals.ipynbLight is an electromagnetic wave — oscillating electric and magnetic fields that propagate through space. In 1865, James Clerk Maxwell unified electricity, magnetism, and optics into four equations that govern all electromagnetic phenomena. We don't need to solve Maxwell's equations directly, but understanding the key result — the wave equation — is essential for everything that follows.
In a material (like ice or air), the electric field $\mathbf{E}$ and magnetic field $\mathbf{B}$ obey Maxwell's equations. For a linear, isotropic, homogeneous medium (one where the material properties don't depend on field strength, direction, or position), these simplify to the wave equation:
$$ \nabla^2 \mathbf{E} = \mu \epsilon \frac{\partial^2 \mathbf{E}}{\partial t^2} $$where:
This equation says: the spatial curvature of the field is proportional to its temporal acceleration. This is the defining property of a wave — the same mathematical form appears in vibrating strings, sound waves, and water waves. The speed of the wave is $v = 1/\sqrt{\mu\epsilon}$.
The simplest solution to the wave equation is a plane wave propagating in one direction (let's call it $z$). If we allow the medium to absorb energy (which ice does), the permittivity $\epsilon$ becomes complex, and the solution is:
$$ E(z,t) = E_0 \, e^{i(\tilde{n} k_0 z - \omega t)} $$where:
This is the central quantity linking Maxwell's equations to optics. To see what the two parts do, substitute $\tilde{n} = n + i\kappa$ into the plane wave:
$$ E(z,t) = E_0 \, e^{i(n k_0 z - \omega t)} \cdot e^{-\kappa k_0 z} $$The first factor is a wave oscillating in space and time with wavelength $\lambda = \lambda_0/n$. The second factor is a decaying exponential.
We measure light using intensity (power per unit area), which is proportional to the square of the electric field amplitude: $I \propto |E|^2$. Since the amplitude decays as $e^{-\kappa k_0 z}$, the intensity decays as:
$$ I(z) = I_0 \, e^{-2\kappa k_0 z} = I_0 \, e^{-\alpha z} $$where the absorption coefficient is:
$$ \alpha = 2\kappa k_0 = \frac{4\pi\kappa}{\lambda_0} $$This exponential decay of intensity with distance is the Beer-Lambert law (also called the Beer-Lambert-Bouguer law). It says that each thin slab of material absorbs the same fraction of the light passing through it. If 1 cm of material absorbs 10% of the light, then 2 cm absorbs not 20% but 19% (because the second centimetre acts on the already-reduced beam).
The absorption coefficient $\alpha$ has units of m$^{-1}$. Its reciprocal $1/\alpha$ is the e-folding distance (or skin depth) — the distance over which the intensity drops to $1/e \approx 37\%$ of its initial value.
For ice, $\kappa$ varies enormously with wavelength:
This enormous contrast is why snow is bright white in the visible (photons scatter many times between grains without being absorbed) but dark in the near-infrared (photons are absorbed within the first few grains).
Each curve shows how the transmitted fraction $I/I_0$ decreases with distance through ice for a different value of $\kappa$:
Blue curve ($\kappa = 10^{-9}$, typical of VIS wavelengths in ice): After 10 cm, essentially 100% of the light survives. The absorption is so weak that a photon could travel 40 metres before losing $1/e$ of its intensity. This is why clean glacier ice can appear blue-green — light at these wavelengths penetrates deep into the ice.
Orange/green curves (intermediate $\kappa$): These show progressively faster absorption. At $\kappa = 10^{-5}$, light is significantly attenuated within a few centimetres.
Red curve ($\kappa = 10^{-3}$, typical of NIR at 1.5 µm): The light is almost completely absorbed within the first millimetre. At these wavelengths, even a single pass through one snow grain ($\sim 200$ µm path) absorbs a substantial fraction of the light.
This wavelength dependence of absorption explains several familiar phenomena:
You will see $\kappa$ referred to variously as the "imaginary refractive index", "extinction coefficient", or "absorption index" in different textbooks. Some authors use $k$ instead of $\kappa$. Be careful with the factor of $4\pi/\lambda$ — some sources define $\alpha$ differently depending on whether they use wavelength in vacuum or in the medium. Throughout this notebook we follow the convention $\alpha = 4\pi\kappa/\lambda_0$ where $\lambda_0$ is the vacuum wavelength.
BioSNICAR connection — The complex refractive index of ice is loaded in
biosnicar/classes/ice.py→calculate_refractive_index()(lines 63–102). Three datasets are available (Warren 1984, Warren & Brandt 2008, Picard 2016), selected by theRFparameter ininputs.yaml. The imaginary part $\kappa(\lambda)$ feeds into the look-up tables that compute single-particle absorption efficiency, which ultimately determines the single-scattering albedo. The data is stored indata/OP_data/480band/rfidx_ice.npz.
The Beer-Lambert law (Section 1) describes absorption — the conversion of light energy into heat. But in snow, another process is equally important: scattering, the redirection of light into new directions.
Scattering occurs whenever a wave encounters a change in refractive index. When a plane wave meets a sphere of ice ($n \approx 1.31$) embedded in air ($n = 1.0$), the wave inside the sphere travels at a different speed than the wave outside. This mismatch distorts the wavefronts, redirecting some energy in new directions.
Think of it by analogy: a water wave hitting a submerged rock generates circular ripples spreading out from the rock. Similarly, an electromagnetic wave hitting an ice grain generates scattered waves radiating outward.
The total power removed from the incident beam by a particle is called extinction. It has two components:
$$ \text{Extinction} = \text{Scattering} + \text{Absorption} $$We quantify scattering and absorption using efficiency factors $Q$, defined as the ratio of the effective cross-section to the geometric cross-section $\pi r^2$ of the sphere:
$$ Q_{\text{ext}} = Q_{\text{sca}} + Q_{\text{abs}}, \qquad \sigma_{\text{ext}} = Q_{\text{ext}} \cdot \pi r^2 $$For example, if a sphere with radius $r = 100$ µm has $Q_{\text{ext}} = 2$, its effective extinction cross-section is $2 \times \pi (100\,\mu\text{m})^2$ — it removes twice as much power from the beam as you'd expect from its physical shadow alone. (This surprising result is explained below.)
$Q$ values are dimensionless and typically range from 0 to ~4:
The physics of scattering depends critically on the ratio of particle size to wavelength, captured by the dimensionless size parameter:
$$ x = \frac{2\pi r}{\lambda} $$This ratio determines whether the particle "looks" small or large to the wave:
| Regime | $x$ | Physical picture | Everyday example |
|---|---|---|---|
| Rayleigh | $x \ll 1$ | Particle much smaller than $\lambda$; the entire particle oscillates as a dipole in the external field. Scattering $\propto \lambda^{-4}$ (short wavelengths scattered much more). Symmetric forward/backward. | Air molecules scattering sunlight → blue sky |
| Mie resonance | $x \sim 1$ | Particle comparable to $\lambda$; complex interference between waves diffracted, refracted, and reflected by the particle. Strong forward scattering. | Water droplets in clouds → white clouds |
| Geometric optics | $x \gg 1$ | Particle much larger than $\lambda$; can be treated as a lens/mirror with rays. $Q_{\text{ext}} \to 2$. Very strong forward scattering. | Raindrops → rainbows |
For snow grains ($r \sim 50$–$1000\,\mu$m) at visible/NIR wavelengths ($\lambda \sim 0.3$–$2.5\,\mu$m), we have $x \sim 100$–$10{,}000$ — firmly in the geometric optics regime. For impurity particles like soot ($r \sim 0.04\,\mu$m), $x \sim 0.1$–$1$, placing them in the Rayleigh–Mie transition — exactly where the physics is most complex.
Rayleigh regime (blue shading, $x < 0.3$): $Q_{\text{ext}}$ increases steeply with $x$. In this regime, scattering efficiency grows as $x^4$ (equivalently, $\lambda^{-4}$). This is why the sky is blue: air molecules have $x \ll 1$ for visible light, and shorter (blue) wavelengths are scattered much more efficiently than longer (red) ones.
Mie resonance regime (green shading, $0.3 < x < 30$): The curve shows complex oscillations. These arise from constructive and destructive interference between waves that take different paths through the sphere (direct transmission, single internal reflection, double internal reflection, etc.). When these paths happen to be in phase, $Q_{\text{ext}}$ peaks; when out of phase, it dips. The oscillation spacing depends on the refractive index contrast.
Geometric optics regime (red shading, $x > 30$): The oscillations damp out and $Q_{\text{ext}}$ converges to 2. This seems paradoxical — how can a sphere remove twice its geometric shadow from a beam?
This is one of the most counter-intuitive results in optics. A large sphere removes power from the forward beam via two mechanisms:
Geometric blocking ($Q = 1$): The sphere physically blocks light rays that hit it, casting a geometric shadow. Some of this light is absorbed, some is scattered to the sides and backwards.
Diffraction ($Q = 1$): Light passing near the edge of the sphere (but not hitting it) is bent by diffraction. This redirected light is also removed from the forward beam. The diffraction pattern has almost the same cross-section as the geometric shadow.
Together: $Q_{\text{ext}} = 1 + 1 = 2$. The "missing" half of the extinction is the diffracted light, which is scattered into a narrow forward cone. For snow modelling, this means that the diffracted component carries nearly half the scattered power but is concentrated so close to the forward direction that it is practically indistinguishable from unscattered light. This is why the delta-Eddington correction (Section 11) is so important.
For snow grains ($r \sim 50$–$1000$ µm at VIS/NIR wavelengths), we have $x \sim 100$–$10{,}000$ — firmly in the geometric optics regime. Even the smallest fresh-snow grains have $x \sim 300$. This means we can use simplified geometric-optics approximations rather than solving the full Mie equations — which is fortunate, because Mie codes become numerically challenging at these large size parameters (tens of thousands of terms in the series expansion).
Impurity particles have much smaller radii and fall into different regimes:
For these, the full Mie theory must be used. BioSNICAR pre-computes the
optical properties using validated Mie codes and stores the results in
look-up tables (lap.npz).
BioSNICAR connection — BioSNICAR uses pre-computed Mie look-up tables rather than solving Mie theory at runtime. Sphere optical properties are retrieved in
biosnicar/optical_properties/op_lookup.py→OpLookupTable.get(). For large hexagonal crystals, geometric optics is used instead:biosnicar/optical_properties/van_diedenhoven.py→calc_ssa_and_g().
Mie theory (Gustav Mie, 1908) is the exact analytical solution for scattering and absorption of a plane wave by a homogeneous sphere. While the full mathematical machinery involves infinite series of Bessel functions and Legendre polynomials, we only need four wavelength-dependent outputs. These are the quantities that feed into the radiative transfer equation.
| Symbol | Name | Range | Physical meaning |
|---|---|---|---|
| $Q_{\text{ext}}$ | Extinction efficiency | 0 to ~4 | Total power removed from the beam, per unit geometric cross-section |
| $Q_{\text{sca}}$ | Scattering efficiency | 0 to ~4 | Power redirected (but not absorbed) |
| $Q_{\text{abs}}$ | Absorption efficiency | 0 to 2 | Power converted to heat inside the particle |
| $\tilde{\omega}$ | Single-scattering albedo | 0 to 1 | Probability that an extinction event is scattering (not absorption) |
| $g$ | Asymmetry parameter | $-1$ to $+1$ | Average cosine of scattering angle |
These are related by: $$ Q_{\text{ext}} = Q_{\text{sca}} + Q_{\text{abs}}, \qquad \tilde{\omega} = \frac{Q_{\text{sca}}}{Q_{\text{ext}}} $$
This is perhaps the most important quantity in snow optics. Think of each time a photon interacts with a grain as a coin flip:
For snow grains in the visible: $\tilde{\omega} \approx 0.999\,99$. This means only about 1 in 100,000 scattering events results in absorption. A photon can scatter thousands of times between grains and still have a high probability of escaping back out through the surface.
For snow grains in the NIR (say 1.5 µm): $\tilde{\omega}$ drops to perhaps 0.95–0.99 for fine grains, or 0.5–0.9 for coarse grains. Now each interaction carries a significant risk of absorption, and a photon that scatters just 10–20 times is likely to be absorbed.
When a photon scatters, it doesn't go in a random direction. The phase function $P(\cos\theta)$ describes the probability of scattering into each angle $\theta$ relative to the original direction. The asymmetry parameter $g$ is the average of $\cos\theta$ over this distribution:
$$ g = \langle \cos\theta \rangle = \frac{1}{2} \int_{-1}^{1} P(\cos\theta) \cos\theta \, d(\cos\theta) $$For snow grains: $g \approx 0.85$–$0.9$. This extreme forward bias means that when a photon scatters off an ice grain, it mostly continues in roughly the same direction. Only a small fraction of scattering events meaningfully redirect the photon. This is why the delta-Eddington correction (Section 11) is essential — it accounts for the fact that much of the nominal "scattering" is really just forward transmission.
A common approximation for the phase function is the Henyey-Greenstein (HG) function:
$$ P_{\text{HG}}(\cos\theta) = \frac{1 - g^2}{(1 + g^2 - 2g\cos\theta)^{3/2}} $$This has the nice property that its single parameter $g$ fully specifies the angular distribution. While not exact for ice crystals (the real phase function has more complex structure), it captures the essential forward bias.
Snow grains have radii of 50–1000 µm, giving size parameters $x = 2\pi r/\lambda$ of 100–20,000 in the VIS/NIR. At these huge $x$:
In this regime, we can think of the photon as a ray that enters the sphere, travels through absorbing ice, and exits. The mean path length through a sphere of radius $r$ (averaged over all impact parameters) is:
$$ \langle l \rangle = \frac{4}{3} r $$Using Beer-Lambert, the fraction of light absorbed in this traversal is:
$$ f_{\text{abs}} = 1 - e^{-\alpha \langle l \rangle} = 1 - \exp\!\left(-\frac{4\pi\kappa}{\lambda} \cdot \frac{4r}{3}\right) $$The absorption efficiency and SSA are then:
$$ Q_{\text{abs}} = 2 f_{\text{abs}}, \qquad Q_{\text{sca}} = 2(1 - f_{\text{abs}}), \qquad \tilde{\omega} = 1 - f_{\text{abs}} $$(The factor of 2 comes from $Q_{\text{ext}} = 2$ normalisation.)
This simple formula connects all the physics we've built up: the imaginary refractive index $\kappa(\lambda)$ from Section 1, the extinction paradox from Section 2, and the Beer-Lambert law — all combined to give us the SSA that controls snow albedo.
Key observations:
These three quantities ($Q_{\text{ext}}$, $\tilde{\omega}$, $g$) are the fundamental inputs to the radiative transfer equation. Everything else — albedo, absorbed flux, transmitted flux — follows from them and the layer geometry.
The key physical insight is that grain size controls absorption through path length: a photon traversing a 1000 µm grain travels 20× further through absorbing ice than one traversing a 50 µm grain, so it has a much higher probability of being absorbed before being scattered back out. In the visible, where $\kappa \sim 10^{-9}$, even the longest path is negligible, so SSA ≈ 1 regardless of grain size. In the NIR, where $\kappa \sim 10^{-4}$, the path length matters enormously.
BioSNICAR connection — Pre-computed Mie efficiencies for ice spheres are stored in look-up tables loaded by
biosnicar/optical_properties/op_lookup.py. The LUTs contain $Q_{\text{ext}}$, $\tilde{\omega}$ (ss_alb), $g$ (asm_prm), and the mass extinction coefficient (ext_cff_mss) as functions of grain radius and wavelength.
Everything we've built so far — Beer-Lambert absorption, Mie scattering efficiencies, the geometric optics approximation — depends on a single material property: the complex refractive index of ice, $\tilde{n}(\lambda) = n(\lambda) + i\kappa(\lambda)$.
This function encodes the entire optical character of ice:
If you know $\tilde{n}(\lambda)$ at all wavelengths, you can compute every optical property of ice grains at every wavelength. The refractive index is where molecular physics meets optics: the values of $n$ and $\kappa$ arise from how the H₂O molecules in the ice crystal lattice respond to electromagnetic radiation.
The imaginary part of the refractive index is controlled by the molecular vibrations of water molecules in the ice lattice:
Measuring $\kappa$ across its 10-order-of-magnitude range is experimentally challenging. Different regions require different techniques: thin-film transmission for the VIS (where absorption is tiny), reflection spectroscopy for the NIR (where absorption is strong). BioSNICAR offers three compilations:
| Code | Source | Notes |
|---|---|---|
Wrn84 |
Warren (1984) | Classic reference, widely used |
Wrn08 |
Warren & Brandt (2008) | Improved NIR absorption bands |
Pic16 |
Picard et al. (2016) | Further NIR refinements |
The real part $n \approx 1.31$ varies slowly with wavelength (slight dispersion — $n$ is higher at shorter wavelengths, causing the separation of colours in ice prisms). The imaginary part $\kappa$ spans from $\sim 10^{-11}$ in the UV to $\sim 1$ at 3 µm.
The imaginary part $\kappa(\lambda)$ has a striking structure:
The huge dynamic range of $\kappa$ (spanning 10 orders of magnitude) is why snow reflectance varies so dramatically with wavelength. It is also why different wavelengths probe different depths in a snowpack: blue light penetrates centimetres to metres, while 1.5 µm light is absorbed in the top millimetre.
The three datasets (Warren 1984, Warren & Brandt 2008, Picard 2016) differ mainly in the NIR, where more precise measurements have refined the absorption band shapes. The differences are small but matter for quantitative retrievals.
BioSNICAR connection —
biosnicar/classes/ice.py:63–102→calculate_refractive_index()loads these datasets fromdata/OP_data/480band/rfidx_ice.npz. The key arrays are namedre_Wrn08andim_Wrn08(for Warren & Brandt 2008, etc.). The choice of dataset is controlled by theRFparameter ininputs.yaml(0 = Wrn84, 1 = Wrn08, 2 = Pic16). The same file also provides pre-computed diffuse Fresnel reflectances used in the adding-doubling solver.
A snowpack is not one sphere — it is a collection of $\sim 10^{12}$ grains per cubic metre. We need to convert single-particle Mie efficiencies into bulk medium optical properties.
For a collection of identical spheres with radius $r$, density $\rho_{\text{ice}} = 917$ kg/m³:
Mass extinction coefficient (m² kg⁻¹): $$ \text{MAC} = \frac{3\, Q_{\text{ext}}}{4\, r\, \rho_{\text{ice}}} $$
This tells us the optical depth per unit mass path.
Single-scattering albedo of the bulk medium equals the single-particle SSA: $$ \tilde{\omega} = \frac{Q_{\text{sca}}}{Q_{\text{ext}}} $$
Asymmetry parameter of the bulk also equals the single-particle $g$ (for identical spheres).
Think of a photon entering a snowpack as a random walk. At each grain, the photon either scatters (probability $\tilde{\omega}$) or is absorbed (probability $1 - \tilde{\omega}$). The absorption probability per grain depends on how far the photon travels through ice before exiting — and that distance is proportional to the grain radius: $\langle l \rangle = 4r/3$.
Consider the journey of a photon in the NIR (say 1.5 µm, where ice absorbs):
In the visible (0.5 µm), $\kappa \sim 10^{-9}$, so the absorption per traversal is negligible regardless of grain size. The photon scatters hundreds of times and almost always escapes → $\tilde{\omega} \approx 1.0$, albedo ≈ 1.0 for all grain sizes.
This explains the fundamental spectral shape of snow: bright in the visible, dark in the NIR, with grain size controlling the NIR.
Snow metamorphism — the process by which snow grains grow and round over time — is therefore an optical ageing process. Temperature gradients, melt-refreeze cycles, and wind packing all increase the effective grain size, darkening the snow in the NIR and reducing its albedo. This creates a positive feedback: darker snow absorbs more energy, which accelerates metamorphism, which further darkens the snow.
The mass extinction coefficient (MAC = $3 Q_{\text{ext}} / 4r\rho$) also decreases with grain size as $1/r$, because larger particles intercept the same fraction of a beam with fewer particles per unit mass. This means that per kilogram, fine snow is a more efficient scatterer than coarse snow.
Key physics from the three panels:
The left panel shows something surprising: MAC is essentially flat across all wavelengths. This is because of the extinction paradox from Section 2.
For ice grains with radii $r = 50$–1000 µm, the size parameter $x = 2\pi r/\lambda$ is always very large ($x \gg 1$) — even at $\lambda = 2.5$ µm, a 50 µm grain has $x \approx 125$. In this geometric optics limit, $Q_{\text{ext}} \approx 2$ at all wavelengths (geometric blocking + diffraction). So:
$$ \text{MAC} = \frac{3 Q_{\text{ext}}}{4 r \rho_{\text{ice}}} \approx \frac{3 \times 2}{4 r \rho_{\text{ice}}} = \frac{3}{2 r \rho_{\text{ice}}} $$This depends only on grain radius, not wavelength. A 100 µm grain always extincts light at ~16 m² kg⁻¹ regardless of whether it's blue or infrared light.
So where does the wavelength dependence come from? Not from extinction, but from the split between scattering and absorption. The middle and right panels reveal the answer:
So while every grain removes the same total amount of light from the beam (MAC is flat), what happens to that light — scattered vs absorbed — depends strongly on wavelength through the imaginary refractive index.
This grain-size sensitivity in the NIR is the basis of remote sensing of snow grain size from satellite observations.
BioSNICAR connection —
biosnicar/optical_properties/column_OPs.py:91–124→get_layer_OPs()retrieves MAC, SSA, and $g$ from look-up tables indexed by grain radius. The MAC formula $3 Q_{\text{ext}} / (4\, r\, \rho)$ is embedded in the LUT values.
Everything so far has assumed snow grains are perfect spheres. In reality, freshly fallen snow crystals are hexagonal plates, stellar dendrites, columns, or needle-like structures. Even after metamorphism rounds the grains, they remain irregular. Why does shape matter?
The key idea is that grain shape changes the internal path length distribution and the scattering phase function. Recall from Section 3 that the absorption efficiency depends on the mean path length through the particle: $\langle l \rangle = 4r/3$ for a sphere. For non-spherical particles, the mean path is different. A thin plate has a shorter mean path (less absorption per interaction) than a sphere of the same volume. A long needle has a longer one.
More importantly, shape affects $g$. A sphere has a very smooth, symmetric internal geometry that produces strong forward scattering. Non-spherical crystals with flat faces, edges, and corners create more complex internal reflections that redirect light to wider angles. This reduces $g$ (making scattering more isotropic), which increases albedo because more photons are scattered back upward.
Shape effects on albedo are typically 1–5% (a few hundredths of albedo) — significant for precise retrievals from satellite data, but secondary compared to grain size (which can change albedo by 0.3 or more in the NIR). The reason is that shape changes $g$ by perhaps 0.05–0.10, whereas grain size changes $\tilde{\omega}$ by 0.5 or more in the NIR. Since $\tilde{\omega}$ controls the probability of absorption per event, it has a stronger effect on the final albedo than the angular redistribution controlled by $g$.
BioSNICAR offers several shape representations, using the shp parameter:
shp |
Shape | Method | Best for |
|---|---|---|---|
| 0 | Sphere | Mie theory | Aged, rounded grains |
| 1 | Sphere + asphericity correction | Mie + He et al. (2017) | General purpose |
| 2 | Spheroid + correction | As above | Slightly non-spherical |
| 3 | Koch snowflake + correction | As above | Complex fractal shapes |
| 4 | Hexagonal prism | Geometric optics (van Diedenhoven) | Fresh crystals |
The asphericity corrections work by adjusting $g$ downward for non-spherical particles while keeping $\tilde{\omega}$ unchanged. For hexagonal prisms (shape 4), a full geometric optics calculation is used, parameterised by the crystal's aspect ratio (side length to length ratio).
The forward-scattering peak is dramatically reduced as particles become less spherical. This has a measurable effect on albedo — non-spherical grains are slightly brighter because more light is scattered sideways and backwards.
In practice, the shape effect on albedo is modest (a few percent) compared to the grain size effect, but it matters for precise retrievals.
BioSNICAR connection — Asphericity corrections are applied in
biosnicar/optical_properties/column_OPs.py→correct_for_asphericity()for shapes 1–3. Hexagonal prisms (shape 4) use a separate geometric optics LUT frombiosnicar/optical_properties/van_diedenhoven.py.
Exercise: Try changing the
shape_factorvalues above and observe how the phase function forward peak changes. What happens to the albedo of a Koch snowflake vs a sphere for the same grain size?
BioSNICAR handles two fundamentally different ice configurations:
layer_type |
Material | Scatterers | Key parameters |
|---|---|---|---|
| 0 | Granular snow/firn | Ice grains in air | Grain radius, snow density |
| 1 | Solid bubbly ice | Air bubbles in ice | Bubble radius, ice density |
Granular snow (type 0): Scattering occurs at grain boundaries where the refractive index jumps from ice (n ≈ 1.31) to air (n = 1). The grain radius determines the optical properties via Mie theory.
Bubbly ice (type 1): The matrix is solid ice, and scattering occurs at air inclusions (bubbles). Here the bubble radius and ice density (which determines the bubble volume fraction) control the optics.
The transition from snow to ice (firn densification) is a continuum, but optically the key variable is the specific surface area (SSA) — the total ice-air interface area per unit mass. Higher SSA means more scattering, which increases albedo.
Key physics:
For a semi-infinite (optically thick) snowpack, density does not appear in the albedo formula at all — only $\tilde{\omega}$ and $g$, which depend on grain size. Density affects how many grains the photon encounters per metre of depth, but in a deep snowpack the photon will scatter until it either escapes or is absorbed regardless of how densely packed the grains are.
Density matters for finite-depth layers (like the sensitivity analysis below), because it controls how much of the snowpack the photon "sees". A thin, low-density layer has less total scattering material, so more light passes through to whatever is below (ground, bare ice, etc.). Think of density as controlling the total amount of scatterer, while grain size controls the scattering efficiency per interaction.
For practical purposes, grain size is the single most important control on clean snow spectral albedo.
BioSNICAR connection — The granular snow (type 0) optics are computed in
biosnicar/optical_properties/column_OPs.py:91–124. Solid bubbly ice (type 1) uses a different approach at lines 128–200, where air bubble Mie properties are combined with the ice matrix absorption.
Exercise: Why does the broadband albedo decrease less steeply for very large grains (>500 µm)? Hint: think about which wavelengths contribute most to the broadband average when NIR albedo is already near zero.
Wet snow and temperate glacier ice contain liquid water, which modifies the optical properties in several ways:
Changed refractive index: Water ($n \approx 1.33$) is close to ice ($n \approx 1.31$), but its absorption spectrum differs — water has stronger absorption at some NIR wavelengths and weaker at others.
Reduced scattering: Water fills air spaces between grains, reducing the refractive index contrast at scattering interfaces. This lowers the scattering efficiency and shifts the apparent grain size.
Coated spheres: In BioSNICAR, liquid water is modelled as a coating on ice grains (Mie theory for coated spheres), which changes the effective Mie efficiencies.
The net effect is that wet snow is slightly darker than dry snow, especially at wavelengths where water absorbs more than ice.
Liquid water darkens snow primarily in the NIR, where water's absorption differs from ice. The effect is modest compared to grain size changes, but measurable — especially around the 1.0 and 1.2 µm water absorption bands.
The dominant optical effect of liquid water is actually through scattering reduction, not absorption change. When water fills the air spaces between grains, the refractive index contrast at grain boundaries drops from $n_{\text{ice}}/n_{\text{air}} \approx 1.31/1.00$ to $n_{\text{ice}}/n_{\text{water}} \approx 1.31/1.33$. The scattering efficiency depends on this contrast — nearly matching refractive indices means much weaker scattering. With fewer scattering events, photons penetrate deeper and are more likely to be absorbed.
This is why wet snow appears visibly darker than dry snow at the same grain size — and why refrozen snow (dry but with large grains from the melt-refreeze cycle) stays dark.
In practice, water content is difficult to retrieve independently from grain size because both affect NIR albedo in similar ways.
BioSNICAR connection — Liquid water is modelled as coated spheres using Mie theory for layered particles in
biosnicar/optical_properties/mie_coated_water_spheres.py→miecoated_driver(). The liquid water content (LWC) is set per layer in the YAML config.
We've now built up all the ingredients:
The question is: given these properties, how much light gets reflected (albedo), how much gets absorbed (heating), and how much passes through? This is the central problem of radiative transfer.
Snow and ice surfaces are typically much wider than they are deep, and their properties vary mainly with depth (not horizontally). This lets us use the plane-parallel approximation: we treat each layer as an infinite horizontal slab, and the radiation field depends only on depth and angle — not on horizontal position.
We describe direction using the cosine of the polar angle: $\mu = \cos\theta$, where $\theta$ is measured from the vertical. $\mu = +1$ is straight up, $\mu = -1$ is straight down, and $\mu = 0$ is horizontal. (The convention varies between textbooks; here $\theta$ is measured from the zenith, so $\mu = \cos(0) = +1$ is up and $\mu = \cos(\pi) = -1$ is down, while $\tau$ increases downward.)
In a plane-parallel scattering and absorbing medium, the monochromatic specific intensity $I(\tau, \mu, \phi)$ obeys:
$$ \mu \frac{dI(\tau, \mu, \phi)}{d\tau} = I(\tau, \mu, \phi) - \frac{\tilde{\omega}}{4\pi} \int_0^{2\pi} \int_{-1}^{1} P(\mu, \phi; \mu', \phi') \, I(\tau, \mu', \phi') \, d\mu' \, d\phi' - S_{\text{solar}} $$Let's unpack each term:
Left-hand side: $\mu \, dI/d\tau$ — the rate of change of intensity along the beam direction. The factor $\mu$ accounts for the path length through a horizontal slab: a beam at angle $\theta$ travels a distance $d\tau/\mu$ through a slab of optical thickness $d\tau$.
First term on the right ($+I$): Extinction — intensity is removed from the beam by both scattering and absorption. Each optical depth unit removes a fraction $dI/I = -d\tau/\mu$ from the beam.
Second term ($-\tilde{\omega}/(4\pi) \int P \cdot I \, d\Omega$): Scattering source — intensity scattered into this direction from all other directions. The phase function $P$ describes how much light is redirected from direction $(\mu', \phi')$ into direction $(\mu, \phi)$. The factor $\tilde{\omega}$ accounts for the fact that only the scattered fraction (not the absorbed fraction) contributes.
Third term ($-S_{\text{solar}}$): Direct solar source — the direct beam from the sun, which adds intensity at the solar zenith angle.
This is an integro-differential equation: the derivative of $I$ depends on an integral of $I$ over all angles. The intensity at any point depends on the intensity arriving from every other direction — which itself depends on the intensity at other points. There is no general closed-form solution.
Exact numerical methods exist (discrete ordinates, Monte Carlo) but are computationally expensive. For snow and ice modelling, where we need solutions at hundreds of wavelengths for many different configurations, we need an approximation — the two-stream method (next section).
↓ ↓ ↓ F_solar (direct + diffuse)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ τ = 0 (top)
↕ scattering events
- - - - - - - - - - - - - - - - - τ = τ₁
↕ more scattering
- - - - - - - - - - - - - - - - - τ = τ₁ + τ₂
↕
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ τ = τ_total (bottom)
↓ F_transmitted
The albedo is the ratio of upward to downward flux at the top surface:
$$ \alpha(\lambda) = \frac{F^{\uparrow}(\tau = 0)}{F^{\downarrow}(\tau = 0)} $$To solve the RTE, we need to simplify it. The most common approach for snow/ice is the two-stream approximation.
BioSNICAR connection — BioSNICAR implements two solvers:
- Adding-doubling:
biosnicar/rt_solvers/adding_doubling_solver.py(more accurate, handles Fresnel corrections)- Toon et al. (1989):
biosnicar/rt_solvers/toon_rt_solver.py(simpler two-stream, slightly faster)
The RTE describes how intensity varies with both depth and angle — it is a function $I(\tau, \mu, \phi)$ of three variables. The two-stream approximation makes a radical simplification: instead of tracking intensity at every angle, we collapse the entire angular distribution into just two numbers at each depth:
This is equivalent to saying: we don't care exactly which angle each photon is travelling at — we only care whether it is going up or down. At each depth, we know the total upward and downward power, and we track how these change with depth.
With this simplification, the integro-differential RTE becomes two coupled ordinary differential equations (ODEs):
$$ \frac{dF^{\downarrow}}{d\tau} = \gamma_1 F^{\downarrow} - \gamma_2 F^{\uparrow} - S^{\downarrow} $$$$ \frac{dF^{\uparrow}}{d\tau} = -\gamma_1 F^{\uparrow} + \gamma_2 F^{\downarrow} + S^{\uparrow} $$The physical meaning of each term:
The $\gamma$ coefficients encode all the physics of the scattering medium ($\tilde{\omega}$, $g$) into two effective rates. Different choices for how to perform the angular integration give different $\gamma$ values, leading to three standard variants:
| Variant | $\gamma_1$ | $\gamma_2$ | Accuracy |
|---|---|---|---|
| Eddington | $\frac{7 - \tilde\omega(4 + 3g)}{4}$ | $\frac{-(1 - \tilde\omega(4 - 3g))}{4}$ | Good all-round; slight errors for conservative scattering |
| Quadrature | $\frac{\sqrt{3}(2 - \tilde\omega(1+g))}{2}$ | $\frac{\tilde\omega\sqrt{3}(1-g)}{2}$ | Best for $\tilde{\omega} \to 1$ (conservative scattering) |
| Hemispheric Mean | $2 - \tilde\omega(1+g)$ | $\tilde\omega(1-g)$ | Simplest; best for thick layers |
All three give the same results to within a few percent for typical snow conditions. BioSNICAR defaults to the Eddington variant.
The two-stream approximation is exact for isotropic scattering ($g = 0$) and becomes less accurate as $g \to 1$. Since snow grains have $g \approx 0.87$, you might worry about accuracy. But the delta-Eddington correction (next section) addresses exactly this: by removing the forward peak from the phase function, it reduces the effective $g$ to $\sim 0.47$, putting us in a regime where the two-stream approximation is accurate.
The alternative — solving the full RTE with, say, 16-stream discrete ordinates — is more accurate but ~100× slower. For a model like BioSNICAR that runs at 480 wavelengths over multi-layer snowpacks, the two-stream approximation with delta-Eddington is the standard balance of speed and accuracy.
The three variants agree closely for moderate optical depths and converge to the same limits as $\tau \to 0$ (transparent) and $\tau \to \infty$ (semi-infinite). The differences are at the few-percent level and are most noticeable for intermediate optical depths. In practice, the choice of variant matters less than the accuracy of the input optical properties.
The Eddington approximation is the most widely used and is BioSNICAR's
default (aprx_typ = 1). It approximates the radiation field as a linear
function of $\mu = \cos\theta$. The Quadrature method evaluates the
radiation field at a specific angle ($\mu = 1/\sqrt{3}$), which is more
accurate for conservative scattering ($\tilde{\omega} \approx 1$). The
Hemispheric Mean averages over each hemisphere, giving the simplest
coefficients.
Why use two-stream at all, rather than solving the full RTE numerically? The full equation has angular, wavelength, and depth dimensions — solving it exactly (e.g., with discrete ordinates or Monte Carlo) is computationally expensive. The two-stream approximation reduces the angular dimension to just two quantities (upward and downward flux), making the solution analytical for each layer. For snow and ice, where the phase function is smooth (well-described by the Henyey-Greenstein function) and the medium is horizontally homogeneous, this approximation is accurate to within a few percent.
BioSNICAR connection — The $\gamma$ coefficients are computed in
biosnicar/rt_solvers/toon_rt_solver.py:279–330→two_stream_approximation(), which implements all three variants. The adding-doubling solver inadding_doubling_solver.pyuses a different but equivalent formulation based on the eigenvalues of the two-stream matrix (lines 296–322). The parameterAPRX_TYPininputs.yamlselects the variant (1 = Eddington, 2 = Quadrature, 3 = Hemispheric Mean).
Snow grains are strongly forward-scattering ($g \approx 0.85$–$0.9$). This means the phase function has a sharp peak near $\theta = 0°$. The two-stream approximation cannot accurately represent this peak, leading to errors in albedo.
The delta-Eddington (or delta-M) correction truncates the forward peak and renormalises the optical properties:
$$ \tau^* = (1 - \tilde{\omega} f) \, \tau $$$$ \tilde{\omega}^* = \frac{(1 - f)\, \tilde{\omega}}{1 - \tilde{\omega} f} $$$$ g^* = \frac{g - f}{1 - f} $$where $f = g^2$ for the delta-Eddington method.
When a photon hits a snow grain with $g \approx 0.87$, about $f = g^2 \approx 76\%$ of the time it continues almost straight forward — indistinguishable from not having scattered at all. Only the remaining 24% of scattering events meaningfully redirect the photon. The delta-Eddington correction acknowledges this: it removes the "fake" forward-scattering events from the optical depth (reducing $\tau$), adjusts the scattering albedo accordingly, and produces a more isotropic effective phase function ($g^* \approx 0.46$) that the two-stream approximation can handle accurately.
Without delta scaling, the two-stream solver overestimates forward transmission (treating strong forward scattering as real scattering events that count toward the diffusion), which underestimates albedo. The correction is essential for snow, where $g$ is high.
Delta-Eddington scaling has a significant impact:
Without delta scaling, two-stream methods underestimate snow albedo by 5–15% in the NIR. It is essential for quantitative accuracy.
The choice of $f = g^2$ comes from matching the first two moments of the phase function and is standard for two-stream approximations (including SNICAR's adding-doubling solver). Multi-stream solvers like DISORT use the more general delta-M scaling with $f = g^N$, where $N$ is the number of streams, to match higher-order moments of the phase function.
BioSNICAR connection — Delta-Eddington scaling is applied in
biosnicar/rt_solvers/adding_doubling_solver.py:296–322→calc_reflectivity_transmittivity(). The scaled properties $\tau^*$, $\tilde{\omega}^*$, $g^*$ are computed before the two-stream eigenvalue solution. The variables are namedts,ws, andgsin the code. The Toon solver applies the same scaling intoon_rt_solver.py:267–277.
Exercise: What happens if you set $f = g^3$ instead of $f = g^2$? (This is the delta-M method with higher-order truncation.) Try modifying
delta_eddington_scaleand observe the effect on albedo.
For a single homogeneous slab with optical depth $\tau$, the two-stream equations have an analytical solution. The reflectance $R$ and transmittance $T$ of the slab depend on four quantities, each with a clear physical interpretation:
| Parameter | Physical meaning | Effect on albedo |
|---|---|---|
| $\tau$ | Optical thickness — total attenuation | Higher $\tau$ → more scattering events → higher R (if $\tilde{\omega} > 0$) |
| $\tilde{\omega}$ | Single-scattering albedo — probability that a scattering event is NOT absorption | Higher $\tilde{\omega}$ → fewer photons absorbed per bounce → higher R |
| $g$ | Asymmetry parameter — degree of forward scattering | Higher $g$ → photons mostly continue forward → lower R (light passes through) |
| $\mu_0$ | Cosine of SZA — controls effective path length | Lower $\mu_0$ (more oblique) → longer path → more scattering → higher R |
The albedo emerges from a competition between scattering (which can redirect photons back out) and absorption (which removes them):
Key observations:
The semi-infinite limit ($\tau \to \infty$) gives a particularly elegant formula:
$$ \alpha_{\infty} = \frac{\gamma_1 - \sqrt{\gamma_1^2 - \gamma_2^2}}{\gamma_2} $$This depends only on $\tilde{\omega}$ and $g$ (through $\gamma_1$, $\gamma_2$), not on $\tau$. This is why the albedo of deep snow depends on grain size (which controls $\tilde{\omega}$) but not on depth.
BioSNICAR connection — The full BioSNICAR solver computes per-layer reflectance and transmittance before combining them with the adding method. The delta-Eddington coefficients and eigenvalue solution in
adding_doubling_solver.py:296–322are equivalent to our toy solver. BioSNICAR also handles the direct-beam source term explicitly, which our simplified version omits for clarity.
Real snowpacks are never homogeneous. A typical winter snowpack might have:
Each layer has different optical properties ($\tau$, $\tilde{\omega}$, $g$), so we cannot treat the whole snowpack as a single slab. We need a method to combine layers — and this is the adding method.
Imagine placing two semi-transparent mirrors facing each other. Light enters from above, passes through the first mirror, bounces off the second, and some fraction bounces back off the first mirror's underside, then off the second again, and so on. Each bounce loses some light to absorption, so the series converges.
This is exactly what happens between snowpack layers. Light transmitted through layer 1 hits layer 2. Some fraction $R_2$ reflects back up. Of this, some fraction $R_1'$ (layer 1's reflectance from below) bounces back down again, and so on:
| Bounce | Path | Contribution to $R_{12}$ |
|---|---|---|
| 0 | Direct reflection off layer 1 | $R_1$ |
| 1 | Through 1, reflect off 2, back through 1 | $T_1 R_2 T_1'$ |
| 2 | Through 1, reflect off 2, reflect off bottom of 1, reflect off 2, through 1 | $T_1 R_2 R_1' R_2 T_1'$ |
| $n$ | $n$ inter-reflections | $T_1 R_2 (R_1' R_2)^{n-1} T_1'$ |
Summing all bounces gives a geometric series:
$$ R_{12} = R_1 + T_1 R_2 T_1' \sum_{n=0}^{\infty} (R_1' R_2)^n = R_1 + \frac{T_1 \cdot R_2 \cdot T_1'}{1 - R_1' \cdot R_2} $$$$ T_{12} = \frac{T_1 \cdot T_2}{1 - R_1' \cdot R_2} $$where:
The product $R_1' R_2$ is always less than 1, because each reflection also involves some absorption. Even in the visible where snow is highly reflective (say $R \approx 0.95$), $R_1' R_2 \approx 0.90$, so the series converges rapidly. In the NIR where $R$ is lower, convergence is even faster. This means the adding formula is exact — no truncation needed.
For an $N$-layer snowpack, we apply the adding formula iteratively, starting from the bottom. We combine the bottom two layers, then add the next layer above, and so on until we reach the surface:
We work bottom-up because reflectance from below is what the adding formula needs at each step. The combined reflectance of everything below the current layer is naturally available at each stage.
This is essentially the same idea as the transfer matrix method in thin film optics — but expressed in terms of reflectance and transmittance rather than electric field amplitudes.
The multi-layer solution shows that:
This wavelength-dependent penetration has several practical implications:
The adding method is exact (given the two-stream R and T values) — it accounts for all orders of inter-reflection between layers, not just single scattering. The geometric series in the denominator converges because $R_1' R_2 < 1$ (each inter-reflection loses energy to absorption).
BioSNICAR connection — The adding method is implemented in
biosnicar/rt_solvers/adding_doubling_solver.py:855–1016→calc_reflection_below()andtrans_refl_at_interfaces(). These functions iterate from the bottom layer upward, combining reflectances using the same formula as ouradd_layers(). BioSNICAR separates direct and diffuse components throughout the adding process, tracking four quantities per interface: direct reflectance, diffuse reflectance, direct transmittance, and diffuse transmittance.
Light-absorbing particles (LAPs) — black carbon, mineral dust, algae — are mixed into the ice medium. BioSNICAR uses external mixing: the impurity optical properties are combined with the ice optical properties at the bulk level, not the single-particle level.
The mixing rules are:
Total optical depth (additive): $$ \tau_{\text{total}} = \tau_{\text{ice}} + \sum_j \tau_{\text{imp},j} $$
where $\tau_{\text{imp},j} = L_{\text{snow}} \cdot c_j \cdot \text{MAC}_j$ with $c_j$ the mass mixing ratio and $L_{\text{snow}}$ the snow mass path.
Effective single-scattering albedo (optical-depth weighted): $$ \tilde{\omega}{\text{eff}} = \frac{\tilde{\omega}{\text{ice}} \tau_{\text{ice}}
Effective asymmetry parameter (further weighted by SSA): $$ g{\text{eff}} = \frac{\tilde{\omega}{\text{ice}} g{\text{ice}} \tau{\text{ice}}
The key insight: even tiny impurity concentrations can dominate in the visible because $\text{MAC}_{\text{BC}} \gg \text{MAC}_{\text{ice}}$ there, while ice barely absorbs. At 500 nm, the mass absorption coefficient of BC is $\sim 10^4$ m$^2$ kg$^{-1}$, while ice absorbs at $\sim 10^{-2}$ m$^2$ kg$^{-1}$ — a factor of $10^6$ difference. This means that ~10 ppb of BC (~10 parts per billion by mass) absorbs as much visible light as the ice itself.
Think of it this way: in clean snow, a photon at visible wavelengths bounces between grains hundreds of times before being absorbed — the absorption probability per scattering event is tiny ($1 - \tilde{\omega} \sim 10^{-7}$). Adding ~10 ppb of BC roughly doubles this per-event absorption probability. Since the photon was previously bouncing ~$10^7$ times before absorption, even a doubling of the per-bounce absorption probability dramatically reduces how many photons escape.
In the NIR, where $\kappa_{\text{ice}}$ is large, a photon is absorbed within a few scattering events regardless of impurities — the ice itself is the dominant absorber. This is why impurities have almost no effect at wavelengths beyond 1 µm.
This wavelength selectivity is key: impurities darken the VIS, grain size darkens the NIR, making them spectrally separable in remote sensing.
The effect of impurities depends on grain size. In coarser snow, the photon takes longer paths through ice per scattering event. With fewer total scattering events before absorption, there are fewer opportunities for the photon to encounter an impurity particle. This means the same concentration of BC has a smaller radiative effect in coarse-grained snow than in fine-grained snow — a phenomenon called the "grain-size–impurity coupling".
The mixing is external (also called "interstitial") — impurity particles sit between ice grains, not inside them. This is a simplification; in reality, BC can be incorporated into ice crystals during riming, which changes the effective MAC through the "lensing" effect of the surrounding ice.
Key physics:
BioSNICAR connection —
biosnicar/optical_properties/column_OPs.py:576–689→mix_in_impurities()implements exactly these mixing rules.
Black carbon (BC, also called soot) is a material produced by the incomplete combustion of fossil fuels, biomass, and biofuels. It consists of small spherules of nearly pure carbon, typically 20–50 nm in diameter, that aggregate into chain-like clusters. It is the substance that makes chimney soot, diesel exhaust, and wildfire smoke dark.
BC is the strongest light-absorbing aerosol per unit mass in the atmosphere. Its optical properties:
| Property | Value | Comparison to ice |
|---|---|---|
| MAC at 550 nm | 7–11 m²/g | ~1,000,000× ice's absorption |
| Spectral dependence | $\text{MAC} \propto \lambda^{-1}$ | Nearly flat ("grey absorber") |
| SSA ($\tilde{\omega}$) | 0.2–0.4 | Ice has $\tilde{\omega} > 0.999$ in VIS |
| Asymmetry $g$ | ~0.5 | Ice grains have $g \approx 0.87$ |
The physical origin of BC's enormous absorption is its electronic structure: carbon's delocalised $\pi$-electrons can absorb photons across a wide range of wavelengths (similar to graphite), unlike most other aerosols whose absorption is limited to specific molecular resonances. This is why BC appears black — it absorbs all visible colours nearly equally.
Even at parts-per-billion (ppb) concentrations — literally one BC particle for every billion ice molecules by mass — BC can reduce snow albedo by 1–5% in the visible. This is enough to significantly accelerate melting through a positive feedback loop:
BioSNICAR offers two BC representations:
mie_sot_ChC90_dns_1317): Fresh BC, recently emittedmiecot_slfsot_ChC90_dns_1317): Aged BC that has
acquired a transparent sulfate coating during atmospheric transport.
The coating acts as a lens, focusing light onto the BC core and
increasing the effective MAC by ~50%.The left panel shows why BC is so effective: its MAC exceeds ice's absorption by 4–6 orders of magnitude in the visible. Even at 1 ppb ($10^{-9}$ mass fraction), BC's contribution to visible absorption is comparable to ice's own.
Smaller grains are more sensitive to BC (right panel). The intuition: in fine-grained snow, a photon scatters many times, taking a long random walk with many opportunities to encounter BC particles. In coarse-grained snow, the photon takes fewer but longer steps through absorbing ice, so it is more likely to be absorbed by the ice itself before encountering BC. Equivalently, clean fine snow has higher visible albedo to begin with — there's more room to darken. This is the "grain-size–impurity coupling".
The snow-albedo feedback amplifies BC's effect: BC reduces albedo → more solar absorption → snow warms and grains grow → albedo drops further (grain growth effect) → more melting exposes more BC (concentration effect). This positive feedback makes BC one of the most important climate-relevant aerosols in snow-covered regions.
Typical BC concentrations in snow: | Location | BC (ppb) | |----------|----------| | Arctic remote | 1–5 | | Arctic near sources | 10–50 | | Alpine/mid-latitude | 5–100 | | Industrial regions | 50–500 | | Near fires | 100–5000 |
BioSNICAR connection — BC optical properties are in
data/OP_data/480band/lap.npzunder keysbc_ChCB_rn40_dns1270__*(uncoated) andmiecot_slfsot_*(coated). The uncoated BC has MAC ≈ 7.5 m² g$^{-1}$ at 550 nm; the coated version is ~1.5× higher due to the sulfate shell acting as a lens. The choice between coated and uncoated depends on the assumed ageing state of the BC and is configured ininputs.yaml.
Mineral dust consists of small particles of weathered rock that are lifted by wind from arid and semi-arid regions (deserts, dried lake beds, glacial outwash plains). These particles can travel thousands of kilometres through the atmosphere before being deposited on snow and ice surfaces.
A crucial point is that "mineral dust" is not a single substance. Its composition — and therefore its optical properties — varies enormously depending on the source geology. The minerals commonly found in dust include:
| Mineral | Effect | Typical abundance |
|---|---|---|
| Quartz (SiO₂) | Scattering only (transparent in VIS) | 10–70% |
| Feldspars (NaAlSi₃O₈ etc.) | Very weak absorption | 5–30% |
| Clay minerals (illite, kaolinite, montmorillonite) | Weak absorption | 20–60% |
| Hematite (Fe₂O₃) | Strong red/VIS absorption | 0–5% |
| Goethite (FeOOH) | Strong blue/UV absorption | 0–10% |
| Calcite (CaCO₃) | Scattering only | Variable |
The key insight is that the iron oxide fraction (hematite + goethite) controls almost all of the dust's ability to absorb light — even though these minerals are often only a few percent of the total mass.
Iron oxides absorb through electronic transitions in the Fe³⁺ ion:
This wavelength dependence is fundamentally different from BC:
| Property | Black carbon | Iron-rich dust | Iron-poor dust |
|---|---|---|---|
| Absorption mechanism | Broadband electronic (graphitic) | Narrow electronic (Fe³⁺) | Negligible |
| Spectral shape | Nearly flat across VIS | Strong blue, weak red | Nearly transparent |
| MAC at 0.5 µm | ~10,000 m² kg⁻¹ | ~300–500 m² kg⁻¹ | ~60–70 m² kg⁻¹ |
| SSA at 0.5 µm | 0.2–0.4 | 0.87–0.92 | 0.95–0.99 |
| Colour on snow | Grey | Orange/pink/brown | Grey/tan |
This is perhaps the most important message about mineral dust in cryospheric science: the optical properties of dust depend strongly on where it comes from. Some examples:
Iron-rich dust (strong absorber):
Iron-poor dust (weak absorber):
BioSNICAR reflects this variability by including multiple dust datasets:
| Dataset | Source region | Iron content | Absorption strength |
|---|---|---|---|
dust_balkanski_central |
Global average (Balkanski et al.) | Moderate | Medium |
dust_skiles |
Colorado Plateau (Skiles et al.) | High | Strong |
dust_greenland_central |
Greenland (general) | Moderate | Medium |
dust_greenland_Cook |
Greenland inland (Cook et al.) | Very low | Weak |
dust_mars |
Mars analogue | Variable | Medium-strong |
Each dataset has five size classes (0.05–5 µm radius), and the optical properties differ not just in magnitude but in spectral shape, because the iron oxide content determines which wavelengths are absorbed.
Dust particles span a wide range of sizes (0.1–100 µm radius), and size affects both the MAC and the SSA. Larger particles:
In practice, the mixture of sizes depends on the dust source and transport distance: long-range transported dust tends to be finer (the larger particles settled out during transport), while locally-sourced dust can be coarser.
Despite being a weaker absorber per unit mass than BC, dust is the dominant light-absorbing impurity on many snow and ice surfaces because:
However, the radiative impact of a given mass of dust varies hugely depending on mineralogy. Models that treat "dust" as a single substance with fixed optical properties can substantially over- or under-estimate its effect. This is why BioSNICAR provides region-specific dust datasets rather than a single generic "dust" type.
These plots illustrate several critical points:
Panel 1 — Mass extinction coefficients: All dust types have MAC values orders of magnitude lower than BC (note the log scale). But look at the differences between dust types: the Balkanski (global average) and Skiles (Colorado) dusts have similar MAC spectra — both are iron-oxide-rich and show strong extinction across the visible. The Greenland inland dust (Cook et al.) has MAC roughly 5× lower — these are quartz- and feldspar-dominated particles that scatter light efficiently but absorb very little.
Panel 2 — Single-scattering albedo: The SSA reveals the split between scattering and absorption. Counterintuitively, the Greenland dust has a lower SSA despite being mineralogically "weaker" — this reflects differences in particle size distribution and geometry, not just composition. The key point is that SSA varies substantially between dust sources, and assuming a single SSA for all "dust" can lead to large errors.
Panel 3 — Albedo impact: At the same mass concentration (100 ppm), iron-rich Balkanski dust causes substantially more visible-wavelength darkening than the iron-poor Greenland dust. Both show the characteristic blue-dominant spectral signature of iron oxide absorption, but the magnitude differs enormously. Compare with BC at 100 ppb — despite being 1000× less mass, BC causes comparable darkening because of its extremely high mass absorption coefficient.
These spectral differences enable remote sensing discrimination of impurity types. A satellite observing snow in the blue (0.45 µm) and red (0.67 µm) can distinguish:
However, discriminating between dust types from spectral observations alone is extremely challenging — the spectral shape is similar (both controlled by Fe³⁺ transitions), only the magnitude differs. This highlights the importance of knowing the dust source when interpreting field or satellite measurements.
BioSNICAR connection — Dust data in
lap.npzincludes multiple regional datasets:dust_balkanski_central,dust_skiles,dust_greenland_central,dust_greenland_Cook, anddust_mars. Each has five size classes (radii ~0.05–5 µm). Choosing the appropriate dataset for your study region is essential — using Saharan dust properties for local Greenland till, or vice versa, can introduce order-of-magnitude errors in radiative forcing estimates.
Snow algae (Chlamydomonas nivalis and relatives) are photosynthetic organisms that darken the snow surface. They are spherical cells (~10–15 µm radius) containing photosynthetic and photoprotective pigments:
Unlike mineral impurities (BC, dust), which are measured in parts per billion by mass (ppb), algae concentrations are measured in cells per mL of meltwater. This reflects how biologists actually measure algae in the field — by melting a snow sample and counting cells under a microscope or with a flow cytometer.
The optical property associated with each algae cell is the extinction cross-section $\sigma_{\text{ext}}$ (m² per cell), not the mass extinction coefficient MAC (m² per kg). The conversion from concentration to optical depth follows:
This matches BioSNICAR's implementation in column_OPs.py:623–627, where
unit == 1 triggers the cell-count conversion pathway. The per-cell
cross-sections are stored in lap.npz under the __ext_xsc suffix,
while mass-based impurities use __ext_cff_mss.
Typical field concentrations:
Key difference from BC: algae absorption is wavelength-selective (pigment bands), while BC is broadband. At visible wavelengths, algae can be more effective per unit mass than BC because the pigment absorption cross-sections are very high.
Algae create a distinctive spectral signature:
This wavelength-specific signature makes algae potentially distinguishable from BC and dust in remote sensing, unlike the spectrally similar effects of grain size and BC.
Important caveat — Unlike BC, dust, and glacier algae, the snow algae optical properties in BioSNICAR are not empirically measured. They are derived from a pigment mixing model (bio-optical model) that combines measured pigment absorption spectra with Mie theory for homogeneous spheres. This model produces a sharp absorption cutoff at ~0.7 µm (the red edge of the pigment absorption), where the single-scattering albedo jumps from ~0.55 to ~1.0 over just 40 nm. This creates an unnaturally sharp spectral step in albedo that real algae (with their heterogeneous internal structure, multiple pigment pools, and cell wall scattering) are unlikely to produce so abruptly. Interpret snow algae results as qualitative indicators of biological darkening effects rather than quantitative predictions.
The glacier algae dataset (Chevrollier et al. 2023, used in Section 18) is empirically derived from field measurements and is more trustworthy.
BioSNICAR connection — Snow algae optical properties are computed by the bio-optical model in
biosnicar/biooptical/biooptical_funcs.py, which calculates MAC from pigment concentrations, cell size, and intracellular absorption. Pre-computed results are stored inlap.npz.
Glacier algae (Ancylonema nordenskiöldii, Mesotaenium berggrenii) are fundamentally different organisms from snow algae, occupying a different ecological niche and posing different optical modelling challenges.
| Property | Snow algae | Glacier algae |
|---|---|---|
| Cell shape | Spherical (~10–15 µm radius) | Cylindrical (~4 µm × 40 µm) |
| Pigments | Chlorophyll + carotenoids | Chlorophyll + purpurogallin |
| Habitat | Wet, melting snow surface | Bare glacier ice surface |
| Colour | Pink/green/orange | Dark brown/purple |
| Typical blooms | Mountain snowfields, spring/summer | Greenland, Alpine glaciers |
| Optical model | Mie theory (spheres) | Geometric optics (cylinders) |
The key optical difference is the purpurogallin-type phenolic pigments found in glacier algae cell walls. These pigments:
The result is that glacier algae cells appear almost black under the microscope — they absorb efficiently across almost all visible wavelengths.
Because glacier algae cells are elongated cylinders (~4 µm diameter × ~40 µm long), Mie theory for spheres is not appropriate. Instead, BioSNICAR uses either:
The empirical approach has the advantage of naturally capturing the complex internal structure of real cells (pigment distribution, cell wall structure, vacuoles), which a simple homogeneous cylinder model would miss.
The western margin of the Greenland Ice Sheet has a distinctive band of darkened bare ice during summer, known as the Dark Zone. This 20–30 km wide band has albedo as low as 0.3 (compared to ~0.55 for clean bare ice), and biological darkening by glacier algae is now recognised as the primary driver of this albedo reduction.
The positive feedback is powerful:
Understanding and modelling this feedback is critical for Greenland Ice Sheet mass balance projections, making accurate glacier algae optical properties essential for BioSNICAR.
The comparison reveals each impurity's distinct spectral fingerprint:
These differences are the foundation for remote sensing retrievals of impurity type and concentration. By measuring reflectance at multiple wavelengths, we can solve an inverse problem:
This is exactly the problem addressed by BioSNICAR's inverse module, which uses the forward model spectra shown here to retrieve impurity concentrations from measured reflectance data.
BioSNICAR connection — Glacier algae optical properties are in
lap.npzunderice_algae_empirical_Chevrollier2023__*(default) orCook2020_glacier_algae_4_40__*(alternative parameterisation). The bio-optical model inbiosnicar/biooptical/can generate custom algae optical properties from cell dimensions and pigment concentrations.
When light crosses the boundary between two media with different refractive indices, it must satisfy electromagnetic boundary conditions — the tangential electric and magnetic fields must be continuous across the interface. The only way to satisfy these conditions for a wave arriving from one side is to have both a transmitted wave (continuing into the second medium) and a reflected wave (going back into the first medium).
This is a universal wave phenomenon. You see it every day:
For unpolarised light at incidence angle $\theta_i$, Fresnel's equations give the reflectance for each polarisation:
$$ R_s = \left| \frac{n_1 \cos\theta_i - n_2 \cos\theta_t}{n_1 \cos\theta_i + n_2 \cos\theta_t} \right|^2 \qquad R_p = \left| \frac{n_1 \cos\theta_t - n_2 \cos\theta_i}{n_1 \cos\theta_t + n_2 \cos\theta_i} \right|^2 $$$$ R = \frac{R_s + R_p}{2} $$where:
At normal incidence ($\theta_i = 0$), both polarisations give the same result:
$$ R_0 = \left(\frac{n_1 - n_2}{n_1 + n_2}\right)^2 $$For air → ice ($n_1 = 1, n_2 = 1.31$): $R_0 = (0.31/2.31)^2 \approx 1.8\%$. This is small but non-negligible for precise modelling.
Brewster's angle ($\theta_B = \arctan(n_2/n_1) \approx 52.6°$ for air→ice): The p-polarised component has zero reflection. All reflected light is s-polarised. This is why the reflected glare from ice or water is partially polarised — and why polarised sunglasses work.
Critical angle for total internal reflection (TIR): When light travels from a denser medium to a less dense one (ice → air), there exists a critical angle $\theta_c = \arcsin(n_1/n_2) \approx 49.7°$ beyond which all light is reflected — none is transmitted. This traps a significant fraction of diffuse light inside ice, enhancing absorption.
For granular snow (BioSNICAR layer_type = 0): Fresnel reflection is
negligible. There is no single flat air-ice interface — instead, the
surface consists of a rough collection of ice grains with air-filled pores.
The incoming beam is scattered by the first grains it encounters, never
"seeing" a coherent flat surface. BioSNICAR skips the Fresnel correction
entirely for granular snow.
For solid ice (BioSNICAR layer_type = 1): There IS a flat, smooth
air-ice interface at the surface, so Fresnel reflection must be accounted
for. This matters because:
Left panel (Fresnel reflectance vs angle):
Right panel (impact on albedo):
TIR deserves special attention because its effect is counter-intuitive. Light that is scattered upward inside the ice and hits the air-ice interface at angles beyond ~50° is reflected back down into the ice. This light gets another chance to be absorbed, effectively increasing the optical path length.
For diffuse upwelling light inside ice (which has a broad angular distribution), a significant fraction (~40%) hits the interface beyond the critical angle and is trapped. This TIR effect:
Computing Fresnel reflectance for diffuse radiation requires integrating over all angles of incidence, weighted by the angular distribution of the radiation field. This integral is computationally expensive, so BioSNICAR pre-computes it:
fl_r_dif_a, fl_r_dif_b) give the hemispherically-averaged Fresnel
reflectance without runtime integrationBioSNICAR connection — The Fresnel correction is applied in
biosnicar/rt_solvers/adding_doubling_solver.py:737–852→calc_correction_fresnel_layer(), which modifies the reflectance and transmittance of the top layer forlayer_type = 1(solid ice). Pre-computed diffuse Fresnel reflectances are loaded fromfl_reflection_diffuse.npz. The correction is skipped entirely for granular snow (layer_type = 0).
Exercise: What is the Fresnel reflectance at the Brewster angle? Why does the Ice→Air curve show total internal reflection? At what solar zenith angle does Fresnel become important (>5%)?
We have now built every component of a radiative transfer solver. Let's pause and appreciate the chain of physics that connects Maxwell's equations to a number called "albedo":
Each step introduces some approximation, but the overall pipeline is remarkably accurate when compared against exact solutions (e.g., DISORT, Monte Carlo) for the geometries relevant to snow and ice.
BioSNICAR Pipeline
==================
1. ICE REFRACTIVE INDEX ← rfidx_ice.npz / inputs.yaml
↓
2. MIE / GEOMETRIC OPTICS ← op_lookup.py / van_diedenhoven.py
↓
3. BULK OPTICAL PROPERTIES ← column_OPs.py → get_layer_OPs()
(MAC, SSA, g per layer)
↓
4. IMPURITY MIXING ← column_OPs.py → mix_in_impurities()
(τ, ω̃, g per layer)
↓
5. DELTA-EDDINGTON SCALING ← adding_doubling_solver.py:296-322
(τ*, ω̃*, g*)
↓
6. LAYER R, T ← calc_reflectivity_transmittivity()
(per-layer reflectance/transmittance)
↓
7. FRESNEL CORRECTION ← calc_correction_fresnel_layer()
(for solid ice surfaces)
↓
8. ADDING METHOD ← calc_reflection_below() +
(combine all layers) trans_refl_at_interfaces()
↓
9. FLUX CALCULATION ← calculate_fluxes()
(F↑, F↓, F_abs per layer)
↓
10. ALBEDO ← α = F↑(0) / F↓(0)
It's worth understanding why we cannot skip any step:
Each approximation step introduces a small error:
| Step | Approximation | Typical error |
|---|---|---|
| Mie theory | Spherical grains (reality: irregular) | 2–5% in $g$ |
| Two-stream | 2 streams (reality: continuous angles) | 1–3% in albedo |
| Delta-Eddington | Forward peak = delta function | <1% (corrects a ~10% error) |
| External mixing | Impurities separate from ice (not embedded) | <1% for typical concentrations |
These errors are largely independent and partially compensating, so the overall pipeline accuracy is typically 1–5% compared to exact solutions — well within the uncertainty of input parameters like grain size and impurity concentration.
Our toy solver implements steps 1–6, 8, and 10. Let's build the complete version.
Left panel (multi-layer vs semi-infinite):
Right panel (energy budget):
Our toy solver, while simpler than BioSNICAR, captures all the essential physics. The key simplifications compared to the full model are:
BioSNICAR connection — The full pipeline is orchestrated by
biosnicar/drivers/run_model.py→run_model(), which calls:setup_snicar()→get_layer_OPs()→mix_in_impurities()→adding_doubling_solver()ortoon_solver(). The entire pipeline runs in ~0.1 s for a typical configuration, making it suitable for inverse problems and ensemble simulations.
The most fundamental check on any radiative transfer solver is conservation of energy: at every wavelength,
$$ F^{\downarrow}_{\text{incident}} = F^{\uparrow}_{\text{reflected}} + F_{\text{absorbed}} + F^{\downarrow}_{\text{transmitted}} $$or equivalently: $\alpha + A + T = 1$ (for unit incident flux).
For a deep snowpack ($\tau \gg 1$), transmitted flux is essentially zero at all wavelengths. For a thin layer over dark ground, transmitted flux is significant and the surface below the snow matters.
Let's verify conservation for various snowpack configurations.
Energy conservation holds to machine precision in all cases. This is a fundamental validation of any radiative transfer solver — if the energy budget doesn't close, the code has a bug. The plots reveal the spectral energy budget:
The absorbed flux profile (how energy is deposited with depth) is important for snow energy balance models. BioSNICAR computes absorbed flux per layer, which can be used to drive snowpack evolution models.
BioSNICAR connection — The energy conservation check is implemented in
biosnicar/rt_solvers/adding_doubling_solver.py:1106–1134→conservation_of_energy_check(), which verifies that the flux sum equals the incident irradiance at every wavelength. If the check fails by more than a threshold, BioSNICAR raises a warning. The flux calculation itself is incalculate_fluxes()(lines 1019–1103), which computes upward, downward, and net fluxes at each layer interface.
Sunlight reaching the snow surface has two distinct components:
1. Direct beam ($F_{\text{dir}}$): Collimated radiation arriving from the sun's direction at zenith angle $\theta_0$. This component has a well-defined direction, and its effective optical depth through the snowpack scales as $\tau / \mu_0$ where $\mu_0 = \cos\theta_0$. Under clear skies, this dominates the total downwelling flux.
2. Diffuse ($F_{\text{dif}}$): Radiation scattered by the atmosphere (Rayleigh scattering, aerosols, clouds). This arrives from all directions across the hemisphere, with no single dominant angle. Under overcast skies, all radiation is diffuse.
Our two-stream solver computes four reflectance/transmittance quantities
per layer (the layer_rt() function):
| Quantity | Symbol | Meaning |
|---|---|---|
| $R_{\text{dif}}$ | rdif |
Reflectance for isotropic (diffuse) illumination |
| $T_{\text{dif}}$ | tdif |
Transmittance for isotropic illumination |
| $R_{\text{dir}}$ | rdir |
Reflectance for collimated beam at angle $\mu_0$ |
| $T_{\text{dir}}$ | tdir |
Transmittance for collimated beam at angle $\mu_0$ |
The diffuse quantities ($R_{\text{dif}}$, $T_{\text{dif}}$) depend only on the optical properties ($\tau$, $\tilde{\omega}$, $g$) and are independent of $\mu_0$. The direct quantities depend on $\mu_0$ through the coefficients $\alpha$ and $\gamma$ in the Briegleb (1992) formulation.
In the adding method (multi-layer), inter-layer reflections use the diffuse R and T (since light that has scattered once becomes diffuse), but the top-of-snowpack albedo uses the direct-beam correction for the incoming beam.
Higher SZA → higher albedo. The intuition:
At SZA = 85° ($\mu_0 \approx 0.087$), the effective optical depth is $\sim 11.5\tau$ — the photon "sees" an enormously thick snowpack and almost always scatters back out.
BioSNICAR separates the treatment through several mechanisms:
direct parameter (0 or 1): Selects whether to compute the direct-beam
or diffuse albedo. When direct=1, the solver uses $\mu_0$ from the solar
zenith angle. When direct=0, the solver performs a Gaussian quadrature
integration over the hemisphere to compute the average diffuse albedo.
Incoming spectral irradiance (incoming parameter): Selects the spectral
shape of the downwelling flux from pre-computed atmospheric profiles. Under
clear skies, the direct beam has a spectrum close to the extraterrestrial
solar spectrum (modified by atmospheric absorption bands at O₃, H₂O, CO₂).
Under cloudy skies, the diffuse flux is spectrally different — clouds absorb
NIR more than VIS, so diffuse radiation is relatively enriched in visible
wavelengths.
Gaussian quadrature for diffuse hemispherical integration:
Rather than a simple average over angles, BioSNICAR uses $n$-point Gaussian
quadrature with carefully chosen angles and weights to compute:
$$R_{\text{dif}} = \int_0^1 R_{\text{dir}}(\mu) \cdot 2\mu \, d\mu
\approx \sum_k w_k \, R_{\text{dir}}(\mu_k)$$
This is implemented in adding_doubling_solver.py:625–703.
The broadband albedo (the single number most relevant for energy balance) is not the simple average of spectral albedo — it is the irradiance-weighted average:
$$\alpha_{\text{BB}} = \frac{\int F_{\downarrow}(\lambda) \, \alpha(\lambda) \, d\lambda}{\int F_{\downarrow}(\lambda) \, d\lambda}$$Because the solar spectrum peaks in the visible (where albedo is high) and drops off in the NIR (where albedo is low), the broadband albedo is higher than the unweighted spectral average. Under cloudy skies, the blue-shifted diffuse spectrum further increases the broadband albedo compared to clear-sky conditions — even if the spectral albedo at each wavelength is unchanged.
Key observations:
The difference between direct and diffuse broadband albedo can be 5–10%, which is important for accurate surface energy budget modelling. Under clear skies, the broadband albedo varies through the day as SZA changes — lower at solar noon, higher at dawn and dusk. Under overcast conditions, albedo is constant throughout the day (no SZA dependence).
This also means that the same snow surface has different albedos under clear vs cloudy skies, even though its physical properties haven't changed. This complicates satellite retrievals: an image taken under clear skies will show lower albedo than one taken under thin clouds, despite the snow being identical.
The ratio of direct to diffuse radiation also varies spectrally. In the UV and blue, Rayleigh scattering makes even clear-sky illumination partially diffuse. In the NIR, the atmosphere is more transparent and the direct fraction is higher. BioSNICAR accounts for this through spectral irradiance profiles loaded from pre-computed atmospheric radiative transfer data.
BioSNICAR connection — The solar zenith angle enters through
illumination.mu_notin the solver. Direct vs diffuse is controlled by thedirectparameter (0 = diffuse, 1 = direct) andincomingselects the spectral irradiance profile. Gaussian quadrature for diffuse hemispherical integration is implemented inadding_doubling_solver.py:625–703→apply_gaussian_integral(), which uses multiple zenith angles to accurately compute the diffuse reflectance.
Let's systematically vary each parameter and examine its effect on spectral albedo. This builds intuition for what controls what — essential knowledge for both forward modelling and inverse retrievals.
We vary one parameter at a time while holding all others at baseline values:
| Parameter | VIS effect | NIR effect | Spectral signature |
|---|---|---|---|
| Grain radius | Negligible | Strong darkening | Broad NIR decrease |
| Density | Weak (thin layers) | Moderate | Uniform scaling |
| Black carbon | Strong darkening | Negligible | Flat VIS decrease |
| Glacier algae | Strong, broadband VIS | Negligible | Broad VIS decrease |
| SZA | Weak | Moderate brightening | Broadband increase |
Grain size → NIR absorption: A photon entering a large grain travels further through absorbing ice before escaping. In the NIR ($\kappa \gg 0$), this extra path leads to more absorption. In the VIS ($\kappa \approx 0$), even long paths don't absorb.
Impurities → VIS absorption: Ice is transparent in the VIS, so a photon scatters many times, encountering many impurity particles. In the NIR, the photon is absorbed by ice within a few scattering events regardless.
Density → total scattering material: More dense snow has more grains per unit volume. For thick layers this barely matters (photon escapes or gets absorbed eventually), but for thin layers it controls optical thickness.
SZA → effective path length: At high SZA, the beam enters obliquely and "sees" a thicker top layer, scattering back out before reaching the absorbing depths.
In real snowpacks, these effects interact:
The key insight for inversions: grain size and impurity type affect different spectral regions, which is why multi-wavelength observations can separate their effects.
Exercise: Run the sensitivity analysis with glacier algae instead of snow algae. How does the spectral signature differ? Can you think of a wavelength ratio that distinguishes glacier algae from black carbon?
If BioSNICAR is installed, we can run the actual forward model and compare with our toy solver. This validates that the physics we built from scratch captures the essential behaviour of the full model.
For the comparison to be meaningful, we must ensure identical inputs to both solvers. Key parameters to match:
solzen (degrees); our toy
model uses mu0 = cos(solzen)layer_type=0),
so we pass layer_type=[0] to BioSNICARdirect=1 for direct beam, matching our toy modelEven with matched inputs, some differences will remain because:
SHP=0)We have built the complete physics of snow and ice radiative transfer from first principles:
| Layer | Concept | Key equation | Toy function |
|---|---|---|---|
| Electromagnetic | Maxwell → wave equation | $E = E_0 e^{i\tilde{n}k_0 z}$ | Beer-Lambert plot |
| Single particle | Mie scattering | $Q_{ext}, \tilde{\omega}, g$ vs $x$ | mie_sphere() |
| Bulk medium | Many particles | $\text{MAC} = 3Q_{ext}/4r\rho$ | mie_sphere() → MAC |
| Impurity mixing | External mixing | $\tau_{tot} = \tau_{ice} + \tau_{imp}$ | mix_impurities() |
| Delta scaling | Forward peak correction | $\tau^*, \tilde\omega^*, g^*$ | delta_eddington_scale() |
| Two-stream | Coupled flux ODEs | $\gamma_1, \gamma_2$ coefficients | single_layer_reflectance() |
| Adding | Layer combination | $R_{12} = R_1 + T_1 R_2 T_1'/(1-R_1'R_2)$ | add_layers() |
| Fresnel | Surface reflection | Snell + Fresnel equations | fresnel_reflectance() |
| Energy | Conservation | $R + A + T = 1$ | toy_snowpack() |
| Concept | BioSNICAR module | Key function |
|---|---|---|
| Ice refractive index | classes/ice.py |
calculate_refractive_index() |
| Mie LUT lookup | optical_properties/op_lookup.py |
OpLookupTable.get() |
| Geometric optics (hex) | optical_properties/van_diedenhoven.py |
calc_ssa_and_g() |
| Granular snow OPs | optical_properties/column_OPs.py |
get_layer_OPs() (type 0) |
| Solid bubbly ice OPs | optical_properties/column_OPs.py |
get_layer_OPs() (type 1) |
| Impurity mixing | optical_properties/column_OPs.py |
mix_in_impurities() |
| Coated spheres | optical_properties/mie_coated_water_spheres.py |
miecoated_driver() |
| Delta-Eddington | rt_solvers/adding_doubling_solver.py |
calc_reflectivity_transmittivity() |
| Two-stream | rt_solvers/toon_rt_solver.py |
two_stream_approximation() |
| Fresnel correction | rt_solvers/adding_doubling_solver.py |
calc_correction_fresnel_layer() |
| Adding method | rt_solvers/adding_doubling_solver.py |
calc_reflection_below() |
| Flux calculation | rt_solvers/adding_doubling_solver.py |
calculate_fluxes() |
| Energy conservation | rt_solvers/adding_doubling_solver.py |
conservation_of_energy_check() |
| Bio-optical model | biooptical/biooptical_funcs.py |
Algae SSP calculation |
| Forward model entry | drivers/run_model.py |
run_model() |
Ice is transparent in the visible, absorbing in the NIR — this is encoded in $\kappa(\lambda)$ and is the root cause of snow's spectral shape.
Grain size controls NIR albedo — larger grains → longer internal paths → more absorption → darker NIR.
Impurities control visible albedo — even ppb of BC absorbs more than ice in the visible because $\text{MAC}_{\text{BC}} \gg \text{MAC}_{\text{ice}}$.
Each impurity has a spectral fingerprint — enabling multi-spectral retrieval of impurity type and concentration.
The two-stream + adding method reduces a continuous integro-differential equation to tractable matrix algebra while maintaining quantitative accuracy.
Delta-Eddington scaling is essential for forward-scattering media like snow.
Energy conservation provides the fundamental validation check for any radiative transfer calculation.