Tutorials Overview
Start with the problem-type guides for a complete IVP, linear BVP, nonlinear BVP, or EVP example. This directory groups the longer tutorials by application and technique.
Tutorial Path
For Beginners
If you're new to spectral methods or Tarang.jl, start here:
- First Steps - Basic workflow and simple diffusion problem
- 2D Rayleigh-Bénard Convection - Complete fluid dynamics example
- Boundary Conditions - Master the boundary condition system
Intermediate Topics
Once comfortable with basics:
- Fluid Dynamics Examples - Navier-Stokes, rotating convection, and turbulence examples
- Surface Dynamics - Fractional Laplacian, surface quasi-geostrophic dynamics
- 3D Turbulent Flow - 3D problems with advanced parallelization
- Analysis and Output - Data management and visualization
- Eigenvalue Problems - Linear stability analysis
Advanced Topics
For experienced users:
- Custom Operators - Define new differential operators
- Optimization Guide - Performance tuning
Tutorial List
Initial Value Problems (InitialValueProblem)
Time-evolution problems where you integrate PDEs forward in time.
| Tutorial | Description | Complexity | Key Features |
|---|---|---|---|
| 2D Rayleigh-Bénard | Thermal convection in 2D | Intermediate | Navier-Stokes, buoyancy, CFL |
| Fluid Dynamics Examples | Navier-Stokes and turbulence examples | Intermediate | Shear flows, rotating convection, turbulence |
| Surface Dynamics | SQG and boundary-coupled dynamics | Advanced | Fractional Laplacian, surface dynamics, SQG inversion |
| 3D Taylor-Green Vortex | 3D turbulence simulation | Advanced | 3D FFTs, energy spectra |
| Channel Flow | Turbulent channel flow | Advanced | Wall-bounded, statistics |
Boundary Value Problems (BVP)
Steady-state problems with boundary conditions.
| Tutorial | Description | Complexity | Key Features |
|---|---|---|---|
| Poisson equation | Steady linear solve | Beginner | Tau constraints, analytic solution |
| 2D Poisson | Periodic strip with mixed walls | Intermediate | Filtered forcing, solution heatmap, residual checks |
Nonlinear Boundary Value Problems
The nonlinear BVP guide gives a self-contained Newton solve, explains the initial guess and convergence controls, and verifies the solution against an analytic profile.
The Lane–Emden tutorial develops a radial application, checks the nonzero solution branch, and plots resolution refinement.
Eigenvalue Problems (EigenvalueProblem)
Linear stability analysis and normal modes.
| Tutorial | Description | Complexity | Key Features |
|---|---|---|---|
| Stability Analysis | Eigenvalue problem setup | Advanced | EigenvalueProblem, eigensolvers |
Surface and Boundary Dynamics
Problems with dynamics confined to surfaces or boundaries.
| Tutorial | Description | Complexity | Key Features |
|---|---|---|---|
| Surface Dynamics | SQG, QG, boundary advection-diffusion | Advanced | Fractional Laplacian, coupled systems |
Wave-Mean Flow Analysis
| Tutorial | Description | Complexity | Key Features |
|---|---|---|---|
| Rotating Shallow Water | Inertia-gravity wave filtering | Intermediate | Temporal filters, wave-mean separation |
| GQL Approximation | Generalized Quasi-Linear methods | Advanced | Wavenumber cutoff, zonal jets |
Special Topics
| Tutorial | Description | Complexity | Key Features |
|---|---|---|---|
| Boundary Conditions | All BC types and usage | Intermediate | Dirichlet, Neumann, Robin |
| Analysis & Output | Data management | Intermediate | NetCDF, analysis |
Problem Types Explained
Initial Value Problems (InitialValueProblem)
Initial value problems evolve fields in time with InitialValueSolver, a timestepper, and initial data.
Boundary Value Problems (BVP)
Linear BVPs solve a steady linear system. Nonlinear BVPs use an initial guess and Newton iteration. Both use BoundaryValueSolver and explicit boundary constraints.
Eigenvalue Problems (EigenvalueProblem)
Eigenvalue problems compute growth rates and modes with EigenvalueSolver. The stability tutorial extends the workflow to hydrodynamic examples.
Choosing a Tutorial
By Physics
Fluid Dynamics:
- Start: 2D Rayleigh-Bénard
- Intermediate: Fluid Dynamics Examples, Surface Dynamics
- Advanced: 3D Turbulence, Channel Flow
Geophysical Flows:
- Start: Surface Dynamics (SQG, QG)
- Intermediate: Rotating Shallow Water (wave-mean separation)
- Advanced: GQL Approximation (zonal jets, turbulence closure)
Heat Transfer:
- Start: First Steps (diffusion)
- Advanced: 2D Rayleigh-Bénard (convection)
Stability Analysis:
- Start: Eigenvalue Problems
By Technique
Want to learn:
- MPI parallelization → Running with MPI
- Boundary conditions → Boundary Conditions
- Output and analysis → Analysis and Output
- 3D problems → 3D Turbulence
By Complexity
Beginner: Basic concepts, single field
Intermediate: Multiple fields, coupled equations
Advanced: 3D problems, advanced analysis
Common Patterns
Setting Up a Simulation
Every tutorial follows this pattern. Here it is in full for 2D heat diffusion — the smallest complete simulation Tarang can run:
# 1. MPI initialization (harmless in serial; needed for multi-rank runs)
using Tarang, MPI
MPI.Initialized() || MPI.Init()
# 2. Domain setup
coords = CartesianCoordinates("x", "y")
dist = Distributor(coords; dtype=Float64, device=CPU())
xbasis = RealFourier(coords["x"]; size=16, bounds=(0.0, 2π))
ybasis = RealFourier(coords["y"]; size=16, bounds=(0.0, 2π))
domain = Domain(dist, (xbasis, ybasis))
# 3. Fields
u = ScalarField(domain, "u")
# 4. Problem
problem = InitialValueProblem([u])
add_parameters!(problem, nu=0.1)
add_equation!(problem, "∂t(u) - nu*Δ(u) = 0")
# add_bc!(problem, "...") # only for bounded (Chebyshev/Jacobi) directions
# 5. Initial condition — use `local_grids`, which returns THIS rank's slab
x, y = local_grids(dist, xbasis, ybasis)
ensure_layout!(u, :g)
get_grid_data(u) .= sin.(x) .* cos.(y')
ensure_layout!(u, :c)
# 6. Solver and time loop
solver = InitialValueSolver(problem, RK222(); dt=1e-3)
t_end = 0.5
while solver.sim_time < t_end
step!(solver)
end
# max|u| = 0.90483742, exactly exp(-2*nu*t_end)MPI.Init() defaults to finalize_atexit=true, so MPI.Finalize() runs on exit by itself — you do not need a cleanup step.
set!(u, (x, y) -> …) builds the global meshgrid, so under MPI it throws DimensionMismatch. local_grids(dist, bases...) gives each rank its own slice and works identically at np = 1, 2, 4, which is why the pattern above uses it.
Adding Analysis
Common analysis tasks, on a solver whose state has a scalar T and a VectorField u:
# Adaptive timestep: CFL takes the SOLVER, and velocities must be VectorFields
cfl = CFL(solver; initial_dt=1e-3, cadence=10, safety=0.4, max_dt=0.01)
add_velocity!(cfl, u)
# File output: base path FIRST, solver SECOND, then one task per quantity
handler = add_file_handler("outputs", solver; sim_dt=0.005, max_writes=10)
add_task!(handler, u; name="u")
add_task!(handler, T; name="T")
# `run!` applies the CFL controller and processes solver-registered handlers
run!(solver; stop_iteration=20, cfl=cfl)
# Custom diagnostics
function compute_diagnostics(u, T)
ke = total_kinetic_energy(u) # Float64: domain integral of ½|u|²
temp_mean = integrate(T) # Float64: quadrature-weighted integral
return (ke=ke, temp=temp_mean)
endThree things that trip people up here:
- Pass field or operator objects to
add_task!, never strings.add_task!(h, "u*u")is accepted silently and then writes a scalar of zeros. - The last component of the base path is the handler name, and each write set gets its own directory:
add_file_handler("outputs", …)writesoutputs/outputs_s1/outputs_s1.nc, and a new_sNset is started everymax_writeswrites (outputs/outputs_s2/…). UseTarang.current_file(handler)to get the path in code. The variables live in NetCDF-4 groups (vars,time,grids), so a plainNetCDF.ncread(file, "u")will not find them — read them withTarang.group_ncread(file, "vars", "u"). AVectorFieldtask is stored with its component axis, e.g.vars/uhas shape(write, component, x, y). add_file_handleralso has a(path, dist, vars)form. That one is not registered with the solver, sorun!will not process it unless you also passoutputs=[handler].
See Analysis and Output for the full output API.
Getting Help
If you're stuck on a tutorial:
- Check the complete example at the end of each tutorial
- Look at the source code in the
examples/directory - Search the API reference for function documentation
- Ask on GitHub Discussions for community help
Contributing Tutorials
We welcome tutorial contributions! See the Contributing Guide for details on:
- Tutorial format and style
- Adding Jupyter notebooks
- Including visualizations
- Testing tutorial code
Next Steps
Ready to start? Pick a tutorial from the list above or continue with:
- 2D Rayleigh-Bénard Convection for a complete fluid dynamics example
- Boundary Conditions to master BC specification
- Running with MPI for parallel computing details