§ Case study · Atmospheric physics · Rust 2026 · ongoing · Shipping

twilight

Your prayer app doesn't know if it's cloudy.

Photons in, prayer times out.

Monte Carlo radiative transfer through a 50-shell spherical atmosphere — the most accurate dawn and dusk calculator ever built. 978 tests. GPU-accelerated on Metal, Vulkan, CUDA, and WebGPU.

  • Rust
  • Monte Carlo
  • GPU
  • radiative transfer
  • no_std
Tests
978
all passing
Single-scatter time
30 ms
Apple Silicon
Atmosphere shells
50
spherical
GPU backends
4
Metal · Vulkan · CUDA · WebGPU

§ Abstract

twilight computes Fajr and Isha prayer times by simulating how sunlight actually scatters through the atmosphere. No lookup tables. No fixed depression angles. Photons in, prayer times out.

Every prayer app hardcodes a solar depression angle. MWL says 18 degrees. Egypt says 15 degrees. Umm al-Qura says 19.5 degrees. They disagree because “when does twilight end?” depends on the atmosphere — not on a number someone picked in 1986.

§ What surfaced

  • Monte Carlo radiative transfer through a 50-shell spherical atmosphere with Rayleigh scattering
  • Five-species molecular gas absorption (O₃, O₂, H₂O, NO₂, O₄ CIA from HITRAN)
  • OPAC aerosols, cloud layers, atmospheric refraction via Snell’s law
  • Full Stokes vector polarization through the optically active path
  • Terrain masking from Copernicus GLO-30 DEM at sub-degree resolution
  • Light pollution modeling via World Atlas of Artificial Sky Brightness
  • Optional live weather from Open-Meteo
  • Optional JPL DE440 ephemeris for sub-arcsecond solar positioning
  • GPU-accelerated on Metal, Vulkan, CUDA, and WebGPU
  • Pure Rust core, #![no_std], embeddable

§ Method

The engine launches photon packets at the sun’s position, propagates them through a discretized atmosphere, and tracks attenuation by absorption and scattering at each shell boundary. The plaintext “twilight ended” decision is made on the resulting illuminance at the observer, not on a precomputed angle.

Compared against fixed-angle methods, twilight is the difference between modeling the atmosphere and guessing it.

Mecca, March equinox, clear sky:

  Fajr:   05:23   depression 14.97    (Egypt 15 says 05:23. Spot on.)
  Isha:   19:32   depression 14.83    (ISNA 18 says 19:45. Off by 13 min.)

Add urban aerosol haze and the answer shifts:

Mecca, March equinox, urban aerosol (AOD 0.30):

  Fajr:   05:32   depression 13.03    (+8 min vs clear sky)
  Isha:   19:25   depression 13.21    (-7 min vs clear sky)

Pull live weather and the engine accounts for today’s actual O₃ column, NO₂ levels, aerosol loading, and cloud cover:

Padborg, Denmark, 2026-03-06, live weather:

  Fajr:   04:28   depression 14.05    AOD 0.11, O3 289 DU, clear sky
  Isha:   18:37   depression 13.59

§ Implementation

Pure Rust. #![no_std] core for embeddability. The host crate provides std bindings, GPU dispatch (wgpu), live-weather pulls, and a CLI. The simulator runs identically on a Mac laptop, a Linux server, and a wgpu-compatible WASM build inside a browser.

Tests cover edge cases that fixed-angle methods get wrong by definition: high latitudes, polar twilight, observer altitude above sea level, dense urban aerosol, full-overcast cloud decks, and refraction-dominated geometry near the horizon.

§ Outcomes

  • 978 tests, all passing — every published edge case covered
  • 30 ms single-scatter on Apple Silicon
  • GPU backends ship for Metal, Vulkan, CUDA, and WebGPU
  • Validated within ±3 minutes against real overcast observations from Denmark, where every other calculator drifts by ten minutes or more
  • Open source — MIT/Apache-2.0 dual-licensed

Let's take the housing off something.

Reverse-engineering, Web3 infrastructure, firmware teardowns, consulting. I answer email inside 24 hours.