# Setting up an experiment In Fortran TRACMASS an experiment is a *project* (the GCM-specific code in `projects//`) plus a *case* (a namelist). You choose them in `Makefile.prj` and recompile. TRACMASS-JAX splits things the same way, but nothing is compiled ahead of time: | Fortran TRACMASS | TRACMASS-JAX | |---|---| | `PROJECT = NEMO` in `Makefile.prj` | `[env.gcm] name = "glorys"`, an adapter module in `tracmass.gcm` | | `CASE = ...`, `namelist_CASE.in` | a named *environment* `[env]` in `tracmass.toml` | | `make && ./runtracmass` | `tracmass.run(env="...")` | This page builds a regional GLORYS12 experiment step by step. Swap `glorys` for `ecco2`, `scrippsgog` or `theoretical` to use another GCM. ## 1. Pick an environment name and a settings file Settings live in [TOML](https://toml.io) files read by [Dynaconf](https://www.dynaconf.com). Each top-level table is an *environment*, and `[default]` holds values shared by all of them. Put a `tracmass.toml` in the directory you run from: ```toml [default] base_output_dir = "/data/raid/trm/" runmonitor_backend = "rich" [omi] dtm_start = "2010-06-01" runtime = "180D" # 180 days forward; "-180D" runs backward move_vertically = false # keep particles on their seeding level output_name = "trm_omi" ``` You can also put the `[omi]` table in its own `trm_omi.toml` next to a shared `tracmass.toml`. Every `trm_*.toml` in the current directory is read too (see [Settings files](settings.md#settings-files)). ## 2. Choose the GCM and the region The `[env.gcm]` table names the adapter, and its optional `subset` limits the part of the grid that is read: ```toml [omi.gcm] name = "glorys" subset = { i1 = 2600, i2 = 3700, j1 = 500, j2 = 1600, k1 = 1, k2 = 2 } ``` `i1`/`i2`/`j1`/`j2` are 0-based Python slice limits on the model's x/y axes, and `k1`/`k2` are 1-based levels. A subset makes every window much cheaper to read. See the [Subsets tutorial](../tutorials/subsets.md) for details, including what happens at the edges. ## 3. Seed the particles The `[env.seed]` table says where particles start: ```toml [omi.seed] approach = "latlon_box" # or "ijk", "latlon_point", "latlon_list" i_sub_num = 10 # 10 x 10 particles per cell j_sub_num = 10 box = { lat1 = -64, lat2 = -62, lon1 = -70, lon2 = -68, k1 = 1, k2 = 1 } ``` See the [Seeding tutorial](../tutorials/seeding.md) for every approach, sub-cell distributions and repeated releases (`seed_freq`). ## 4. Choose the integrator and its options ```toml [omi] integrator = "time_dependent_patched" # full grid / patched / streaming traj_max_time = "90D" # stop each particle 90 days after release rampup_windows = 2 # denser output in the first two days ``` | Integrator | Reads per window | Good for | |---|---|---| | `time_dependent` (default) | the whole (sub)grid | small grids, subsets, particles everywhere | | `time_dependent_patched` | a box around the particles | clustered particles on a large grid | | `time_dependent_streaming` | the six faces of each particle's cell | scattered particles, very long runs | See [Memory-efficient integration](../tutorials/memory.md). ## 5. Run ```python import tracmass result = tracmass.run(env="omi") # all from settings result = tracmass.run("2011-06-01", env="omi") # override the start date result = tracmass.run(env="omi", iter_sub=4, verbose=True) ``` `tracmass.run` resolves every argument you leave out from the active environment: | Argument | From settings when omitted | |---|---| | `gcm` | `[env.gcm] name` | | `dtm_start` | `dtm_start`, else the adapter's own default date | | `dtm_end` | `dtm_end`, else `dtm_start + runtime`, else one window | | `integrator` | `integrator`, default `"time_dependent"` | | `state` | the `[env.seed]` table | | `verbose` | `verbose`, default `false` | Other keyword arguments, such as `iter_sub`, `patch_buffer` or `n_windows`, go straight to the integrator. The integrator in turn reads `monitor`, `recorder`, `no_wflux`, `n_particle_batches`, `traj_max_time`, `seed_freq` and the ramp-up options from the settings when they are not passed. ## 6. Find the output With `output_name` set, the trajectories are written to ```text {base_output_dir}/{output_name}_{forward|reverse}_{dtm_start}.parquet ``` e.g. `/data/raid/trm/trm_omi_forward_2010-06-01.parquet`. Read them back with ```python df = tracmass.load(env="omi") # newest omi file df = tracmass.load(env="omi", lonlat=True) # with lon/lat columns ``` See [Output](../output.md). ## The same thing in plain Python Every step above has a Python equivalent. That is useful in notebooks and for experiments that settings cannot express: ```python import tracmass from tracmass import gcm, seed tracmass.settings.setenv("omi") # optional grid, lazy = tracmass.new_flux( "glorys", dtm_start="2010-06-01", dtm_end="2010-11-28" ) state = seed.latlon_box(-64, -62, -70, -68, grid=grid, gcm="glorys", i_sub_num=10, j_sub_num=10) result = tracmass.time_dependent_patched( state, grid, lazy, iter_sub=4, monitor="rich", recorder="omi_test.parquet", ) ```