Oceananigans.jl — Agent Rules
Project Overview
Oceananigans.jl is a Julia package for fast, friendly, flexible, ocean-flavored fluid dynamics on CPUs and GPUs. It solves the incompressible (Boussinesq) Navier-Stokes equations with models including: nonhydrostatic (with free surfaces), hydrostatic free-surface, and shallow water — on RectilinearGrid, LatitudeLongitudeGrid, CubedSphereGrid, and ImmersedBoundaryGrid.
Language & Environment
Julia 1.10+ | CPU and GPU (CUDA, AMD, Metal, OneAPI)
Key packages: KernelAbstractions.jl, CUDA.jl, Enzyme.jl, Reactant.jl
Style: ExplicitImports.jl for source code;
using Oceananigansfor examples/tests
Critical Rules
Kernel Functions (GPU compatibility)
Use
@kernel/@index(KernelAbstractions.jl)Kernels must be type-stable and allocation-free
Use
ifelse— never short-circuitingif/elsein kernelsNo error messages, no Models inside kernels
Mark functions called inside kernels with
@inlineNever loop over grid points outside kernels — use
launch!
Type Stability & Memory
All structs must be concretely typed
Type annotations are for dispatch, not documentation
Minimize allocation; favor inline computation
Never hardcode Float64: no literal
0.0or1.0in kernels or constructors. Usezero(grid),one(grid),convert(FT, 1//2), or rational literals
Imports
Source code: explicit imports (checked by tests)
Examples/docs: rely on
using Oceananigans; never explicitly import exported names
Docstrings
Use DocStringExtensions.jl with
$(SIGNATURES)ALWAYS
jldoctestblocks, NEVER plainjuliablocks — doctests are tested; plain blocks rotInclude
# outputwith verifiable output; prefershowmethods over boolean comparisonsUse unicode for math (
Δt,η,ρ), not LaTeX — LaTeX doesn't render in the REPL
Model Constructors
gridis positional:NonhydrostaticModel(grid; closure=nothing)ShallowWaterModel(grid, gravitational_acceleration; ...)— both positionalOmit semicolon when there are no keyword arguments:
NonhydrostaticModel(grid)notNonhydrostaticModel(grid;)
Naming Conventions
Files: snake_case matching the type they define —
nonhydrostatic_model.jlTypes/Constructors: PascalCase only for true constructors —
NonhydrostaticModelFunctions: snake_case —
time_step!; functions that return values are never PascalCaseKernels: may prefix with underscore —
_compute_tendency_kernelVariables: English long name or readable unicode math notation — never mix abbreviated and full forms (e.g.,
condvscondition) to imply a difference; be specific
Module Structure
src/
├── Oceananigans.jl # Main module, exports
├── Architectures.jl # CPU/GPU architecture abstractions
├── Grids/ # Grid types and constructors
├── Fields/ # Field types and operations
├── Operators/ # Finite difference operators
├── BoundaryConditions/ # Boundary condition types
├── Models/ # Model implementations
│ ├── NonhydrostaticModels/
│ ├── HydrostaticFreeSurfaceModels/
│ ├── ShallowWaterModels/
│ └── LagrangianParticleTracking/
├── TimeSteppers/ # Time stepping schemes
├── Solvers/ # Poisson and tridiagonal solvers
├── TurbulenceClosures/ # LES and eddy viscosity models
├── Advection/ # Advection schemes
├── BuoyancyFormulations/ # Buoyancy models
├── OutputWriters/ # File I/O
├── Simulations/ # High-level simulation interface
└── Utils/ # Utilities and helpersCommon Pitfalls
Type instability in kernels ruins GPU performance
Overconstraining types: use annotations for dispatch, not documentation
Missing imports: tests will catch this — add to
usingstatementsPlain
juliablocks in docstrings: always usejldoctestSubtle bugs from missing method imports, especially in extensions
Expecting unexported names: consider exporting them rather than changing user scripts
Extending
getpropertyto fix undefined property bugs: fix on the caller side instead"Type is not callable" errors: variable name shadows a function — rename or qualify
Quick fixes that break correctness: if a test fails after a change, revisit the original edit
Commented-out code: delete it. Git is the journal — don't leave commented code, debugging artifacts, or stale copy-paste remnants
2D indexing on fields: always use 3D indexing (
field[i, j, k]). 2D indexing works by coincidence on some fields but is unsupported and will breakHardcoded Float64: never use
0.0,1.0in kernels or constructors; usezero(grid)etc.Scope creep in PRs: keep changes focused on a single concern. Unrelated cleanup goes in a separate PR
Modifying Project.toml dependencies: never add, remove, or change
[deps]or[weakdeps]in the rootProject.tomlunless the task absolutely requires it. Dependency changes have wide-reaching consequences — they affect CI, load time, and downstream compatibility. Only touch[compat]bounds when explicitly asked.
Git Workflow
Follow ColPrac. Feature branches, descriptive commits, update tests and docs with code changes, check CI before merging.
Design Principles
Dispatch over conditionals: use Julia's type system and multiple dispatch instead of
if/elsebranching. Backend-specific code goes inext/extensions, notifbranches insrc/Use
on_architecturefor data transfers — never manualArray()/CuArray()callsDefaults serve the common case: avoid
nothingdefaults when a concrete default (likeCPU()) covers 80% of usage. Minimize boilerplate for the typical user.Keyword argument names must be consistent across related types and constructors
Always use explicit
returnin functions longer than one expressionOne operation per line as default; break long expressions across lines
Agent Behavior
Prioritize type stability and GPU compatibility
Follow established patterns in existing code
Add tests for new functionality; update exports when adding public API
Reference physics equations in comments when implementing dynamics
Further Reading
Detailed reference docs are in .agents/ — read on demand:
| Document | Content |
|---|---|
.agents/testing.md | Full testing guidelines, running tests, debugging |
.agents/documentation.md | Building docs, fast builds, doctest details, writing examples |
.agents/validation.md | Reproducing paper results step-by-step |
Auto-loading Rules
Rules in .claude/rules/ load automatically when you touch matching files:
kernel-rules.md— GPU kernel requirements (src/)docstring-rules.md— docstring and jldoctest conventions (src/)testing-rules.md— test writing and running (test/)docs-rules.md— documentation building and style (docs/)examples-rules.md— Literate.jl example conventions (examples/)
Skills (slash commands)
/run-tests— run targeted tests, prioritized by what's likely to break/build-docs— build documentation locally/add-feature— checklist for adding new physics/features/new-simulation— set up, run, and visualize a new simulation (with or without a reference paper)/babysit-ci— monitor CI, auto-fix small issues, pause on bigger problems, retrigger flaky runs