ArchimedLight.jl

ArchimedLight.jl is the Julia reimplementation of the ARCHIMED light model. This model computes the interception and scattering of light by complex 3D scenes, with a focus on performance. It uses a rasterization-based approach for first-order interception and an iterative method for scattering, with flexible options for optical properties and directional response.

It is designed around a simple workflow: build or read a scene, define optical models, create a LightSimulation, then call run_light for one meteo row or a complete meteo table.

<details> <summary>Reproducing the figures</summary>

The animation runs the wheat and agrivoltaic wheat scenes from the archimedlight-benchmark-scenes artifact every 30 minutes over a representative clear-sky day. Each plot has about 2,500 explicit ground tiles, making the moving projected shade visible while the same color scale tracks incident PAR irradiance through the day. The script to reproduce these figures is in docs/make_video.jl. </details>

Scope

  • ARCHIMED-style scene/model/meteo ingestion: .ops, .opf, .gwa, YAML models, and meteo CSV files
  • File-based and in-memory workflows through the same runtime API
  • Directional sky discretization with the standard ARCHIMED turtle sector counts
  • First-order interception by CPU rasterization / z-buffer style projection
  • Iterative scattering using the same directional visibility information
  • Attachment of Ri_* and Ra_* values back onto MTG nodes for inspection and export
  • Fixture-based parity work against the historical Java implementation

Energy balance, transpiration, and photosynthesis are intentionally out of scope for this package. The historical ARCHIMED documents referenced throughout this site still matter for the model vocabulary and physical assumptions, but the Julia package documented here currently implements the light-only core.

Quick Start

using ArchimedLight

repo_root = normpath(joinpath(dirname(pathof(ArchimedLight)), ".."))
config = joinpath(repo_root, "example_2", "config.yml")
sim, meteo = read_simulation(config)

step = run_light(sim, first(meteo))

step.budget.incident_flux.total.par;
step.budget.absorbed_energy.total.par;
Dict{Int64, Float64} with 5968 entries:
  3988 => 87.5534
  601  => 25.5139
  1356 => 384.701
  4651 => 1136.27
  3233 => 2121.01
  960  => 781.042
  2874 => 606.986
  205  => 1199.29
  5010 => 1151.45
  5406 => 1340.5
  2478 => 42.6067
  2082 => 861.706
  5369 => 1185.55
  5802 => 1308.39
  564  => 30.0428
  2837 => 87.6434
  4255 => 873.327
  3629 => 28.8527
  3196 => 72.1572
  ⋮    => ⋮

The simulation results are grouped by quantity and waveband in LightBudget. When you attach those values back onto the scene, the default attribute names keep the standard ARCHIMED naming convention such as Ri_PAR_f, Ri_PAR_q, and Ra_PAR_q.

Read This Site In Three Passes

  • Start with Getting Started if you want one runnable coffee example with the minimum number of moving parts.
  • Continue with Beginner Workflows, File-Based Workflow, or Interactive Workflow depending on whether your scene already exists on disk or is being built in Julia.
  • Use the reference pages for exact file keys, scene semantics, model structure, meteo columns, and outputs.

Documentation Map

Contributors