|
| 1 | +# AGNI — Copilot Instructions |
| 2 | + |
| 3 | +AGNI is a Julia package that simulates radiative-convective equilibrium (RCE) in extreme rocky-exoplanet atmospheres. It wraps the Fortran SOCRATES radiative transfer code via a Julia FFI layer. |
| 4 | + |
| 5 | +## Build, Test, and Run |
| 6 | + |
| 7 | +### Prerequisites |
| 8 | +`RAD_DIR` must be set to a compiled SOCRATES installation before any Julia invocation: |
| 9 | +```bash |
| 10 | +export RAD_DIR=/path/to/SOCRATES |
| 11 | +``` |
| 12 | + |
| 13 | +### Build (install Julia packages + compile SOCRATES Julia wrappers) |
| 14 | +```bash |
| 15 | +julia --project=. -e 'using Pkg; Pkg.build()' |
| 16 | +``` |
| 17 | + |
| 18 | +### Run the model |
| 19 | +```bash |
| 20 | +julia agni.jl # uses res/config/default.toml |
| 21 | +julia agni.jl res/config/hotdry.toml # use a specific config |
| 22 | +``` |
| 23 | + |
| 24 | +### Run all tests |
| 25 | +```bash |
| 26 | +cd test/ |
| 27 | +julia --project=.. runtests.jl |
| 28 | +``` |
| 29 | + |
| 30 | +### Run fast tests only (skips integration tests) |
| 31 | +```bash |
| 32 | +cd test/ |
| 33 | +julia --project=.. runtests.jl fast |
| 34 | +``` |
| 35 | + |
| 36 | +### Run a single test file |
| 37 | +```bash |
| 38 | +cd test/ |
| 39 | +julia --project=.. -e 'include("test_phys.jl")' |
| 40 | +``` |
| 41 | + |
| 42 | +### Generate coverage |
| 43 | +```bash |
| 44 | +cd test/ |
| 45 | +julia --project=.. --code-coverage runtests.jl |
| 46 | +julia --project=.. ../test/get_coverage.jl |
| 47 | +``` |
| 48 | + |
| 49 | +## Architecture |
| 50 | + |
| 51 | +The package entry point is `src/AGNI.jl`, which `include()`s submodule files **in a fixed order** (order matters for dependencies) and then imports them. The executable `agni.jl` activates the project, imports `AGNI`, and calls `AGNI.main()`. |
| 52 | + |
| 53 | +### Central data structure |
| 54 | +`atmosphere.Atmos_t` (defined in `src/atmosphere.jl`) is a mutable struct that holds all model state: pressure/temperature grids, flux arrays, gas mixing ratios, solver flags, file paths, and physics options. Nearly every function takes an `atmos::Atmos_t` as its first argument and mutates it. |
| 55 | + |
| 56 | +### Typical execution flow (`AGNI.run_from_config`) |
| 57 | +1. Parse and validate the TOML config dict |
| 58 | +2. Instantiate `Atmos_t` → `atmosphere.setup!` → `atmosphere.allocate!` |
| 59 | +3. Optionally set deep heating profile (`atmosphere.set_deep_heating!`) |
| 60 | +4. Initialize T(p) profile via `setpt.request!` |
| 61 | +5. Run `chemistry.calc_composition!` |
| 62 | +6. Call the requested solver (`solver.solve_energy!` or `solver.solve_transparent!`) |
| 63 | +7. Write outputs: `save.write_ncdf`, `save.write_profile`, then plotting functions |
| 64 | + |
| 65 | +### Submodule responsibilities |
| 66 | +| Module | Role | |
| 67 | +|---|---| |
| 68 | +| `atmosphere` | `Atmos_t` struct, setup/allocate/deallocate, hydrostatic integrator | |
| 69 | +| `energy` | Flux calculations: SOCRATES RT, MLT convection, conduction, latent/sensible heat | |
| 70 | +| `solver` | Nonlinear solvers (Newton, Gauss-Newton, Levenberg-Marquardt, Jacobi-Newton) | |
| 71 | +| `setpt` | Setting initial T(p) profiles (dry adiabat, saturation, Guillot, custom) | |
| 72 | +| `spectrum` | Spectral file loading and management | |
| 73 | +| `chemistry` | Thermochemical equilibrium via FastChem; rainout logic | |
| 74 | +| `ocean` | Surface liquid ocean formation and distribution | |
| 75 | +| `rfm` | Optional line-by-line RT via the RFM code | |
| 76 | +| `phys` | Physical utility functions (EOS, thermodynamics) | |
| 77 | +| `consts` | Physical constants | |
| 78 | +| `save` | NetCDF and CSV output | |
| 79 | +| `plotting` | Makie/GR-based diagnostic plots | |
| 80 | +| `load` | Reading profiles and external data | |
| 81 | +| `guillot` / `blake` | Analytic T(p) profile implementations | |
| 82 | + |
| 83 | +### External dependencies |
| 84 | +- **SOCRATES** (Fortran RT code, loaded at runtime via `include(ENV["RAD_DIR"]/julia/src/SOCRATES.jl)`). The `atmosphere` module hard-includes this path on load. |
| 85 | +- **FastChem** (optional, for thermochemical equilibrium). Fetched by `src/get_fastchem.sh`. |
| 86 | +- **RFM** (optional, line-by-line RT). Used only when `files.rfm_parfile` is set in config. |
| 87 | + |
| 88 | +## Key Conventions |
| 89 | + |
| 90 | +### Module files must not be run directly |
| 91 | +Every `src/*.jl` file begins with: |
| 92 | +```julia |
| 93 | +if (abspath(PROGRAM_FILE) == @__FILE__) |
| 94 | + error("The file '$thisfile' is not for direct execution") |
| 95 | +end |
| 96 | +``` |
| 97 | + |
| 98 | +### `include()` order in `src/AGNI.jl` is load-order dependent |
| 99 | +New source files must be added at the correct position in `AGNI.jl`'s `include` list (dependencies before dependents) and then explicitly `import`ed and `export`ed. |
| 100 | + |
| 101 | +### Bang (`!`) functions mutate `Atmos_t` |
| 102 | +Functions like `setup!`, `allocate!`, `deallocate!`, `set_deep_heating!` follow the Julia convention of mutating their primary argument in place and returning `Bool` (true = success). |
| 103 | + |
| 104 | +### Configuration is TOML-driven |
| 105 | +All physics options, file paths, solver settings, and output flags come from a single TOML config file. The config dict is validated in `AGNI.open_config` and `AGNI.run_from_config` before any model objects are created. Add new config keys there first. |
| 106 | + |
| 107 | +### Logging |
| 108 | +Use Julia's `@info`, `@warn`, `@debug`, `@error` macros (not `println`). Verbosity is controlled by `execution.verbosity` in the config (0 = silent, 1 = normal, 2 = debug). |
| 109 | + |
| 110 | +### Pressure and unit conventions |
| 111 | +- Pressures in TOML configs are in **bar**; internally AGNI works in **Pa** (×1e5 conversion). |
| 112 | +- Temperatures in K, fluxes in W m⁻², lengths in m throughout the Julia code. |
| 113 | + |
| 114 | +### Test suite structure |
| 115 | +Unit tests are individual files (`test_consts.jl`, `test_phys.jl`, etc.) included by `runtests.jl`. Integration tests (`test_integration.jl`) require SOCRATES data and are skipped with the `fast` argument. Add new unit test files by `include()`ing them in `runtests.jl`. |
0 commit comments