diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 000000000..a0451d35c --- /dev/null +++ b/.cursorrules @@ -0,0 +1,125 @@ +###################################################################### +# .cursorrules – project-level instructions for Cursor AI # +# Target repo: github.com/mflowcode/mfc # +# Format: plain-text "rules for the Agent". One idea per line. # +###################################################################### + +### ─────────────────────────────────────────────────────────────────── +### 1. Global project context (ALWAYS applied) +### ─────────────────────────────────────────────────────────────────── + +- You are interacting with **MFC** – an exascale, many-physics, multi-component + flow solver written in modern Fortran and generated with the Fypp + pre-processor. Most source files use the `.fpp` extension (Fypp templates) + and are transpiled to `.f90` during the CMake build. A minority of modules + remain as plain `.f90`. The code lives in `src/`, tests in `tests/`, + and example input cases in `examples/`. + +- Fypp helper macros live in files under any `include/` directory within + `src/` (e.g., `src//include/`). **Scan these macro files first** so + that template expansions resolve correctly. + +- Always assume free-form Fortran 2008+ (`.fpp` and `.f90`) with `implicit none`, + explicit `intent(in|out|inout)`, and modern constructs (`allocate`, + `move_alloc`, `iso_fortran_env`, etc.). + +- Prefer `module` + `contains` → `subroutine foo()` patterns; avoid COMMON + blocks and `include` files. + +- **Simulation kernels are accelerated exclusively with OpenACC.** Always + include the appropriate `!$acc` pragmas when generating or modifying + performance-critical loops. + +- **The codebase is written in Fortran 2008+ with the Fypp pre-processor.** + Always use the appropriate Fypp macros when generating or modifying + performance-critical loops. + +- **Before suggesting or applying any source-code changes, first read/parse the + full codebase *and* the documentation sources listed below, then produce a + concise description of how the codebase is structured and functions.** + +- Documentation sources: + - Primary online docs: + - Root-level `README.md` in the repository. + +### ─────────────────────────────────────────────────────────────────── +### 2. Style & naming conventions (AUTO-ATTACH for *.fpp and *.f90 files) +### ─────────────────────────────────────────────────────────────────── + +- Indent 2 spaces; continuation lines line up under “&”. +- No maximum line length is enforced. +- Prefer shorter, streamlined code—avoid needless verbosity while keeping clarity. +- Lower-case keywords (`do`, `end subroutine`, etc.). +- Module names: `m_` (e.g., `m_transport`). +- Public procedures: `_` (e.g., `compute_flux`) with prefixe `s_` or `f_` for subroutines and functions, respectively. +- Avoid private helper functions within a subroutine or function, and instead make them private to the module (if appropriate) +- Helper functions or subroutines start with with f_[name here] or s_[name here], respectively +- Avoid passing arguments to subroutines and functions that need to be reshaped in the subroutine or function, such that the compiler can optimize the code. +- Avoid common Fortran code smells, such as: + - Use of `goto` statements (except in legacy interop situations). + - Omission of `intent(...)` declarations. + - Use of global state via `COMMON` blocks or `save` variables. + - Shadowing of variable names (especially loop indices). + - Non-descriptive or single-letter variable names outside small scopes. + - Excessively long helper procedures (>200 lines); prefer decomposition. + - Excessively long subroutines (>500 lines); prefer decomposition. + - Excessively long functions (>100 lines); prefer decomposition. + - Excessively long modules (>1000 lines); prefer decomposition. + - Excessively long files (>1000 lines); prefer decomposition. + - Subroutines and functions that are too long to be understood at a glance. + - Use of `!$acc routine seq` to mark subroutines and functions that are called from OpenACC parallel loops. + - Mixing I/O logic with computation (separate concerns). + - Missing implicit none statements. + - Missing `intent(in|out|inout)` declarations. + - Missing `dimension` or `allocatable`/`pointer` attributes. + - Missing `private` declarations. + - Missing `public` declarations. + - Missing `module procedure` declarations. + - Missing `use` statements. + - Declaring arrays without `dimension` or `allocatable`/`pointer` attributes. + - Use of `stop` for error handling (prefer use of the subroutine `s_mpi_abort` with an appropriate string message argument). + +### ─────────────────────────────────────────────────────────────────── +### 3. Test workflow (AUTOMATICALLY applied when the code is significantly changed and should be tested) +### ─────────────────────────────────────────────────────────────────── + +- Run the test suite after any meaningful code change to verify correctness. +- Ask the user to alter the test suite command so that only the relevant tests are run. +- When you think you are done with the code changes, run ./mfc.sh test -j $(nproc) -f EA8FA07E -t 9E2CA336 +- Otherwise, only run specific tests that are relevant to the code changes. +- Do not run ./mfc.sh test -j $(nproc) without any other arguments (it takes too long to run all tests). + +### ─────────────────────────────────────────────────────────────────── +### 4. OpenACC programming guidelines (AUTOMATICALLY applied to *.fpp/*.f90) +### ─────────────────────────────────────────────────────────────────── + +- **Prefer:** + + !$acc parallel loop gang vector default(present) + + around tight loops over cells or particles; fall back to `!$acc kernels` + only when loop dependencies prevent direct parallelization. Always add + `reduction` clauses where needed. + +- Use `collapse(n)` in `!$acc parallel loop` pragmas to combine nested loops + when it improves parallelism and the iterations are independent. + +- Use `private(var1, var2, ...)` clauses for all variables that are local + to a parallel region or loop, especially scalar temporaries and loop counters. + +- Use `!$acc routine seq` to mark subroutines and functions that are called from OpenACC parallel loops. + +- When adding `!$acc routine seq` put it on the first line after the declaration of the subroutine or function. + +- Allocate large arrays with the `managed` attribute or move them to the device + at program start using a persistent `!$acc enter data` region. + +- Do **not** place `stop` or `error stop` statements inside OpenACC parallel regions or loops, as they are unsupported in device code and will cause runtime failures. + +- Ensure the code compiles with Cray Fortran (`ftn`) and NVIDIA HPC SDK + (`nvfortran`) for OpenACC GPU offloading, and with GNU (`gfortran`) and Intel + (`ifx`/`ifort`) for CPU-only builds where OpenACC directives are ignored. + +###################################################################### +# End of file +######################################################################