Tutorial

Folder: examples/tutorial

This folder contains the smallest TARSA examples that still use real meteorology. For a first run, start with minimal_code.jl. Use 01_run_point_source.jl when you want the same Etna case saved as tutorial_plume.nc for the GIF step in 02_make_plume_gif.jl.

Purpose

This tutorial keeps the workflow short:

  1. get ERA5 automatically,
  2. load it into TARSA.InputFields,
  3. place a point source on the ERA5 grid,
  4. run it through AerosolTracer,
  5. save a GIF-ready plume NetCDF,
  6. optionally render a GIF of the plume.

The source is deliberately simple so the main idea stays clear: you can work directly with real ERA5 winds, density, and vertical structure without writing a large driver script.

What this tutorial uses

The checked-in tutorial case uses:

SettingValue
RegionMediterranean box around Etna
Requested boxlon = 12-18, lat = 34-40
Date2024-04-01 to 2024-04-02
Source typesteady point source
Source locationnear Etna (15.0, 37.75)
Emission rate8 kg/s
Injection height2500 m
Vertical spreadsigma_z = 600 m
TracerAerosolTracer(radius_m=0.11e-6, density_kg_m3=1700.0)
Solverexplicit :dst_koren_rk3
Tutorial runtimetwo requested ERA5 days (48 hourly steps)

Before you run

You need:

  • Julia with the TARSA project instantiated
  • internet access on the first run, unless the ERA5 files are already cached

ERA5 download requires Copernicus credentials, either through ~/.cdsapirc or through the CDSAPI_URL and CDSAPI_KEY environment variables. The exact setup is described in Guide / Data Access.

The repository also ships the exact tutorial ERA5 subset in examples/tutorial/data/:

  • era5_2024_04_01_levels.nc
  • era5_2024_04_01_surface.nc
  • era5_2024_04_01_precip.nc

This means a new user can usually run the tutorial immediately without waiting for a fresh Copernicus request. If you remove these files and force a new download, budget roughly 10 minutes for the Copernicus transfer and about 1 minute for the actual TARSA tutorial computation.

Pipeline

Download or reuse ERA5

The tutorial begins by resolving the meteorology files. The repository already includes the required tutorial files in examples/tutorial/data/, so they are normally reused immediately. If they are missing, TARSA downloads them automatically.

Core step:

levels_file, surface_file, precip_file, _ = TARSA.prepare_input_data(
    CASE.lat_min,
    CASE.lat_max,
    CASE.lon_min,
    CASE.lon_max,
    CASE.year,
    CASE.month,
    CASE.days;
    download_cams=false,
    data_dir=DATA_DIR,
)

Load meteorology into TARSA

Once the files exist, the tutorial uses the high-level loader:

input = TARSA.load_input_data(levels_file, surface_file)

This creates a single InputFields object that carries the meteorology, coordinates, and grid spacing.

Build a point source on the ERA5 grid

The source is built with:

emissions = TARSA.zero_emissions(input)
TARSA.add_point_source!(
    emissions,
    input,
    SOURCE.lon,
    SOURCE.lat;
    rate_kg_s=SOURCE.rate_kg_s,
    injection_height=SOURCE.injection_height_m,
    sigma_z=SOURCE.sigma_z_m,
)

This is the key tutorial step. The source is defined in physical coordinates and TARSA maps it directly onto the loaded ERA5 grid.

Configure and run the aerosol solver

The actual simulation path is short:

  1. Load the aerosol process inputs:
aerosol_inputs = TARSA.load_aerosol_inputs(
    levels_file,
    precip_file;
    surface_file=surface_file,
)
  1. Build the solver configuration:
solver = TARSA.ExplicitSolver(
    cfl=SOLVER.cfl,
    scheme=SOLVER.scheme,
    dt=SOLVER.dt_seconds,
)
  1. Turn meteorology and emissions into an aerosol simulation object:
sim = TARSA.build_aerosol_simulation(
    input,
    emissions;
    aerosol=AEROSOL,
    aerosol_inputs=aerosol_inputs,
    processes=TARSA.AerosolProcesses(
        sedimentation=true,
        wet_deposition=TARSA.WetDeposition(),
        dry_deposition=TARSA.DryDeposition(lai=fill(2.0f0, input.Nx, input.Ny)),
    ),
    solver=solver,
    lateral_bc=:neumann0,
    bottom_bc=:neumann0,
)
  1. Run the model:
mixing_ratio = TARSA.run!(sim)

This is still the main high-level TARSA pattern to remember, now using the public aerosol API directly.

Write the plume output

The only extra step beyond minimal_code.jl is saving the plume file that the GIF script expects:

TARSA.save_results(
    OUTPUT_FILE,
    input,
    mixing_ratio,
    emissions;
    template_file=levels_file,
    variables=["concentration"],
    save_emissions=false,
)

This writes:

  • out/tutorial_plume.nc

The NetCDF file is created from the ERA5 template and adds the simulated concentration field plus the source and aerosol metadata used by the plotting step.

Make the GIF

After the tutorial run, you can render the plume animation with:

julia --project=. examples/tutorial/02_make_plume_gif.jl

This writes:

  • out/tutorial_plume_surface.gif

The GIF shows the evolving near-surface concentration over the tutorial domain and marks the source location.

48-hour Etna plume animation

How to run

For the shortest path:

julia --project=. examples/tutorial/minimal_code.jl

This writes:

  • examples/tutorial/out/quickstart_etna.nc

For the tutorial run used for the GIF:

From the repository root:

julia --project=. examples/tutorial/01_run_point_source.jl

Or from inside examples/tutorial/:

julia --project=../.. minimal_code.jl
julia --project=../.. 01_run_point_source.jl

What to expect

This is a real-meteorology run, so the plume does not follow an idealized straight path. Its transport depends on the ERA5 winds in the chosen time window.

What should stay true:

  • the source is anchored near the chosen volcano point,
  • the final plume shifts downwind relative to the source,
  • tutorial_plume.nc contains nonzero concentration values.

How to adapt this tutorial

For the shortest case edits, change the parameter values near the top of examples/tutorial/minimal_code.jl.

For examples/tutorial/01_run_point_source.jl, the quickest edits are:

  • CASE: change the date window or domain,
  • SOURCE: change location, rate, injection height, or vertical spread,
  • AEROSOL: change particle radius or density,
  • SOLVER: change cfl, scheme, or model time step.

Good first adaptations:

  • move the source to a different volcano or industrial stack,
  • shrink the domain for a faster first run,
  • edit CASE.days to request a shorter or longer period,
  • vary AEROSOL.radius_m or AEROSOL.density_kg_m3,
  • test how plume spread changes with a different sigma_z.

If you want the same tutorial pattern with a surface source instead of an elevated plume, use:

emissions = TARSA.zero_emissions(input)
TARSA.add_ground_source!(
    emissions,
    input,
    SOURCE.lon,
    SOURCE.lat;
    rate_kg_s=SOURCE.rate_kg_s,
)

If you want full control, build the 4D volumetric emissions array directly:

emissions = TARSA.build_custom_emissions(input) do E, input
    dz = TARSA.calculate_dz_full(input.geopotential)
    i = argmin(abs.(input.longitude .- SOURCE.lon))
    j = argmin(abs.(input.latitude .- SOURCE.lat))
    rate_t = fill(Float32(SOURCE.rate_kg_s), input.Nt)

    for t in 1:input.Nt
        volume = input.dx[i, j] * input.dy[i, j] * dz[i, j, 1, t]
        E[i, j, 1, t] = rate_t[t] / volume
    end
end