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:
  4986 => 1298.61
  4700 => 1117.87
  4576 => 1126.83
  6073 => 107.383
  2288 => 56.1529
  1703 => 81.5081
  1956 => 839.459
  2350 => 844.308
  5975 => 552.69
  3406 => 208.614
  2841 => 1241.04
  2876 => 26.6719
  687  => 347.622
  185  => 1090.16
  1090 => 1240.13
  2015 => 438.546
  3293 => 396.755
  3220 => 7.49491
  4888 => 1177.71
  ⋮    => ⋮

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