|
| 1 | +# Oceananigans.jl rules for agent-assisted development |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +Oceananigans.jl is a Julia package for fast, friendly, flexible, ocean-flavored fluid dynamics simulations on CPUs and GPUs. |
| 6 | +It provides a framework for solving the incompressible (or Boussinesq) Navier-Stokes equations with various model configurations including: |
| 7 | +- Nonhydrostatic models with free surfaces |
| 8 | +- Hydrostatic models for large-scale ocean simulations |
| 9 | +- Shallow water models |
| 10 | +- Support for a variety of grids: RectilinearGrid, LatitudeLongitudeGrid, CubedSphereGrid |
| 11 | +- Support for complex domains using ImmersedBoundaryGrid |
| 12 | + |
| 13 | +## Language & Environment |
| 14 | +- **Language**: Julia 1.10+ |
| 15 | +- **Architectures**: CPU and GPU (CUDA, AMD, Metal, OneAPI) |
| 16 | +- **Key Packages**: KernelAbstractions.jl, CUDA.jl, Enzyme.jl, Reactant.jl, AMDGPU.jl, Metal.jl, oneAPI.jl |
| 17 | +- **Testing**: Comprehensive test suite covering all model types and features |
| 18 | + |
| 19 | +## Code Style & Conventions |
| 20 | + |
| 21 | +### Julia Best Practices |
| 22 | +1. **Explicit Imports**: Use `ExplicitImports.jl` style - explicitly import all used functions/types |
| 23 | + - Import from modules explicitly (already done in src/Oceananigans.jl) |
| 24 | + - Tests automatically check for proper imports |
| 25 | + |
| 26 | +2. **Type Stability**: Prioritize type-stable code for performance |
| 27 | + - All structs must be concretely typed |
| 28 | + |
| 29 | +3. **Kernel Functions**: For GPU compatibility: |
| 30 | + - Use KernelAbstractions.jl syntax for kernels, eg `@kernel`, `@index` |
| 31 | + - Keep kernels type-stable and allocation-free |
| 32 | + - Short-circuiting if-statements should be avoided if possible, ifelse should always be used if possible |
| 33 | + - No error messages inside kernels |
| 34 | + - Models _never_ go inside kernels |
| 35 | + |
| 36 | +4. **Documentation**: |
| 37 | + - Use DocStringExtensions.jl for consistent docstrings |
| 38 | + - Include `$(SIGNATURES)` for automatic signature documentation |
| 39 | + - Add examples in docstrings when helpful |
| 40 | + |
| 41 | +5. **Memory efficiency** |
| 42 | + - Favor doing lots of computations inline versus allocating temporary memory |
| 43 | + - Generally minimize memory allocation |
| 44 | + - Design solutions that work within the existing framework |
| 45 | + |
| 46 | +### Naming Conventions |
| 47 | +- **Files**: snake_case (e.g., `nonhydrostatic_model.jl`, `compute_hydrostatic_free_surface_tendencies.jl`) |
| 48 | +- **Types**: PascalCase (e.g., `NonhydrostaticModel`, `HydrostaticFreeSurfaceModel`, `SeawaterBuoyancy`) |
| 49 | +- **Functions**: snake_case (e.g., `time_step!`, `compute_tendencies!`) |
| 50 | +- **Kernels**: "Kernels" (functions prefixed with `@kernel`) may be prefixed with an underscore (e.g., `_compute_tendency_kernel`) |
| 51 | +- **Variables**: Use _either_ an English long name, or mathematical notation with readable unicode |
| 52 | + |
| 53 | +### Module Structure |
| 54 | +``` |
| 55 | +src/ |
| 56 | +├── Oceananigans.jl # Main module, exports |
| 57 | +├── Architectures.jl # CPU/GPU architecture abstractions |
| 58 | +├── Grids/ # Grid types and constructors |
| 59 | +├── Fields/ # Field types and operations |
| 60 | +├── Operators/ # Finite difference operators |
| 61 | +├── BoundaryConditions/ # Boundary condition types |
| 62 | +├── Models/ # Model implementations |
| 63 | +│ ├── NonhydrostaticModels/ |
| 64 | +│ ├── HydrostaticFreeSurfaceModels/ |
| 65 | +│ ├── ShallowWaterModels/ |
| 66 | +│ └── LagrangianParticleTracking/ |
| 67 | +├── TimeSteppers/ # Time stepping schemes |
| 68 | +├── Solvers/ # Poisson and tridiagonal solvers |
| 69 | +├── TurbulenceClosures/ # LES and eddy viscosity models |
| 70 | +├── Advection/ # Advection schemes |
| 71 | +├── BuoyancyFormulations/ # Buoyancy models |
| 72 | +├── OutputWriters/ # File I/O |
| 73 | +├── Simulations/ # High-level simulation interface |
| 74 | +└── Utils/ # Utilities and helpers |
| 75 | +``` |
| 76 | + |
| 77 | +## Testing Guidelines |
| 78 | + |
| 79 | +### Running Tests |
| 80 | +```julia |
| 81 | +# All tests |
| 82 | +Pkg.test("Oceananigans") |
| 83 | + |
| 84 | +# Run specific test groups by setting the TEST_GROUP environment variable |
| 85 | +ENV["TEST_GROUP"] = "unit" # or "time_stepping", "regression", etc. |
| 86 | +Pkg.test("Oceananigans") |
| 87 | + |
| 88 | +# CPU-only (disable GPU) |
| 89 | +ENV["CUDA_VISIBLE_DEVICES"] = "-1" |
| 90 | +ENV["TEST_ARCHITECTURE"] = "CPU" |
| 91 | +Pkg.test("Oceananigans") |
| 92 | +``` |
| 93 | + |
| 94 | +* GPU tests may fail with "dynamic invocation error". In that case, the tests should be run on CPU. |
| 95 | + If the error goes away, the problem is GPU-specific, and often a type-inference issue. |
| 96 | + |
| 97 | +### Writing Tests |
| 98 | +- Place tests in `test/` directory |
| 99 | +- Follow the existing test group structure |
| 100 | +- Test on both CPU and GPU when possible |
| 101 | +- Name test files descriptively (snake_case) |
| 102 | +- Include both unit tests and integration tests |
| 103 | +- Test numerical accuracy where analytical solutions exist |
| 104 | + |
| 105 | +### Quality Assurance |
| 106 | +- Ensure doctests pass |
| 107 | +- Use Aqua.jl for package quality checks |
| 108 | + |
| 109 | +## Common Development Tasks |
| 110 | + |
| 111 | +### Adding New Physics or Features |
| 112 | +1. Create module in appropriate subdirectory |
| 113 | +2. Define types/structs with docstrings |
| 114 | +3. Implement kernel functions (GPU-compatible) |
| 115 | +4. Add unit tests |
| 116 | +5. If the user interface is changed, update main module exports in `src/Oceananigans.jl` |
| 117 | +6. Add validation examples in `validation/` or `examples/` when appropriate |
| 118 | + |
| 119 | +### Modifying Core Models |
| 120 | +- Nonhydrostatic model: `src/Models/NonhydrostaticModels/` |
| 121 | +- Hydrostatic model: `src/Models/HydrostaticFreeSurfaceModels/` |
| 122 | +- Shallow water model: `src/Models/ShallowWaterModels/` |
| 123 | +- Time stepping: `src/TimeSteppers/` |
| 124 | +- Always maintain compatibility with existing model types |
| 125 | + |
| 126 | +## Documentation |
| 127 | + |
| 128 | +### Building Docs Locally |
| 129 | +```sh |
| 130 | +julia --project=docs/ docs/make.jl |
| 131 | +``` |
| 132 | + |
| 133 | +### Viewing Docs |
| 134 | +```julia |
| 135 | +using LiveServer |
| 136 | +serve(dir="docs/build") |
| 137 | +``` |
| 138 | + |
| 139 | +### Documentation Style |
| 140 | +- Use Documenter.jl syntax for cross-references |
| 141 | +- Include code examples in documentation pages |
| 142 | +- Add references to papers from the literature by adding bibtex to `oceananigans.bib`, and then |
| 143 | + a corresponding citation |
| 144 | +- Make use of cross-references with equations |
| 145 | + |
| 146 | +### Writing examples |
| 147 | +- Explain at the top of the file what a simulation is doing |
| 148 | +- Let code "speak for itself" as much as possible, to keep an explanation concise. |
| 149 | + In other words, use a Literate style. |
| 150 | +- Use visualization interspersed with model setup or simulation running when needed to |
| 151 | + give an understanding of a complex grid, initial condition, or other model property. |
| 152 | +- Look at previous examples. New examples should add as much value as possible while |
| 153 | + remaining simple. This requires judiciously introducing new features and doing creative |
| 154 | + and surprising things with simulations that will spark readers' imagination. |
| 155 | + |
| 156 | +## Important Files to Know |
| 157 | + |
| 158 | +### Core Implementation |
| 159 | +- `src/Oceananigans.jl` - Main module, all exports |
| 160 | +- `src/Models/NonhydrostaticModels/nonhydrostatic_model.jl` - Nonhydrostatic model definition |
| 161 | +- `src/Models/HydrostaticFreeSurfaceModels/hydrostatic_free_surface_model.jl` - Hydrostatic model |
| 162 | +- `src/Grids/` - Grid implementations |
| 163 | +- `src/Fields/` - Field types and operations |
| 164 | +- `src/TimeSteppers/` - Time integration schemes |
| 165 | + |
| 166 | +### Configuration |
| 167 | +- `Project.toml` - Package dependencies and compat bounds |
| 168 | +- `test/runtests.jl` - Test configuration |
| 169 | + |
| 170 | +### Examples |
| 171 | +- `examples/langmuir_turbulence.jl` - Ocean mixed layer with Langmuir turbulence |
| 172 | +- `examples/internal_wave.jl` - Internal wave propagation |
| 173 | +- `examples/shallow_water_Bickley_jet.jl` - Shallow water instability |
| 174 | +- `examples/baroclinic_adjustment.jl` - Baroclinic instability |
| 175 | +- `examples/two_dimensional_turbulence.jl` - 2D turbulence |
| 176 | +- Many more examples in the `examples/` directory |
| 177 | + |
| 178 | +## Physics Domain Knowledge |
| 179 | + |
| 180 | +### Ocean and Fluid Dynamics |
| 181 | +- Incompressible/Boussinesq approximation for ocean flows |
| 182 | +- Hydrostatic approximation for large-scale flows |
| 183 | +- Free surface dynamics with implicit/explicit time stepping |
| 184 | +- Coriolis effects and planetary rotation |
| 185 | +- Stratification and buoyancy-driven flows |
| 186 | +- Turbulence modeling via LES and eddy viscosity closures |
| 187 | + |
| 188 | +### Numerical Methods |
| 189 | +- Finite volume on structured grids (Arakawa C-grid) |
| 190 | +- Staggered grid locations: velocities at cell faces, tracers at cell centers |
| 191 | +- Various advection schemes: centered, upwind, WENO |
| 192 | +- Pressure Poisson solver for incompressibility constraint |
| 193 | +- Time stepping: RungeKutta, Adams-Bashforth, Quasi-Adams-Bashforth |
| 194 | +- Take care of staggered grid location when writing operators or designing diagnostics |
| 195 | + |
| 196 | +## Common Pitfalls |
| 197 | + |
| 198 | +1. **Type Instability**: Especially in kernel functions - ruins GPU performance |
| 199 | +2. **Overconstraining types**: Julia compiler can infer types. Type annotations should be used primarily for _multiple dispatch_, not for documentation. |
| 200 | +3. **Forgetting Explicit Imports**: Tests will fail - add to using statements |
| 201 | + |
| 202 | + |
| 203 | +## Git Workflow |
| 204 | +- Follow ColPrac (Collaborative Practices for Community Packages) |
| 205 | +- Create feature branches for new work |
| 206 | +- Write descriptive commit messages |
| 207 | +- Update tests and documentation with code changes |
| 208 | +- Check CI passes before merging |
| 209 | + |
| 210 | +## Helpful Resources |
| 211 | +- Oceananigans docs: https://clima.github.io/OceananigansDocumentation/stable/ |
| 212 | +- Discussions: https://github.com/CliMA/Oceananigans.jl/discussions |
| 213 | +- KernelAbstractions.jl: https://github.com/JuliaGPU/KernelAbstractions.jl |
| 214 | +- Reactant.jl: https://github.com/EnzymeAD/Reactant.jl |
| 215 | +- Reactant.jl docs: https://enzymead.github.io/Reactant.jl/stable/ |
| 216 | +- Enzyme.jl: https://github.com/EnzymeAD/Enzyme.jl |
| 217 | +- Enzyme.jl docs: https://enzyme.mit.edu/julia/dev |
| 218 | +- YASGuide: https://github.com/jrevels/YASGuide |
| 219 | +- ColPrac: https://github.com/SciML/ColPrac |
| 220 | + |
| 221 | +## When Unsure |
| 222 | +1. Check existing examples in `examples/` directory |
| 223 | +2. Look at similar implementations in the codebase |
| 224 | +3. Review tests for usage patterns |
| 225 | +4. Ask in GitHub discussions |
| 226 | +5. Check documentation in `docs/src/` |
| 227 | +6. Check validation cases in `validation/` |
| 228 | + |
| 229 | +## AI Assistant Behavior |
| 230 | +- Prioritize type stability and GPU compatibility |
| 231 | +- Follow established patterns in existing code |
| 232 | +- Add tests for new functionality |
| 233 | +- Update exports in main module when adding public API |
| 234 | +- Consider both CPU and GPU architectures |
| 235 | +- Reference physics equations in comments when implementing dynamics |
| 236 | +- Maintain consistency with the existing codebase style |
| 237 | + |
| 238 | +## Current Development Focus |
| 239 | + |
| 240 | +Active areas of development to be aware of: |
| 241 | + |
| 242 | +- **Performance optimization**: Reactant.jl integration for XLA compilation |
| 243 | +- **Enzyme.jl integration**: Automatic differentiation support |
| 244 | +- **Multi-architecture support**: AMD, Metal, OneAPI in addition to CUDA |
| 245 | +- **MPI/distributed computing**: Improvements to distributed grid capabilities |
| 246 | +- **Output improvements**: NetCDF and other output format enhancements |
| 247 | +- **Grid flexibility**: Enhanced support for lat-lon, cubed sphere, immersed boundaries |
| 248 | +- **Lagrangian particle tracking**: Enhanced particle capabilities |
| 249 | +- **Validation**: Expanding the validation test suite |
0 commit comments