Skip to content

Commit d36d1bb

Browse files
authored
Create .cursorrules (#866)
1 parent df51a3c commit d36d1bb

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

.cursorrules

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
######################################################################
2+
# .cursorrules – project-level instructions for Cursor AI #
3+
# Target repo: github.com/mflowcode/mfc #
4+
# Format: plain-text "rules for the Agent". One idea per line. #
5+
######################################################################
6+
7+
### ───────────────────────────────────────────────────────────────────
8+
### 1. Global project context (ALWAYS applied)
9+
### ───────────────────────────────────────────────────────────────────
10+
11+
- You are interacting with **MFC** – an exascale, many-physics, multi-component
12+
flow solver written in modern Fortran and generated with the Fypp
13+
pre-processor. Most source files use the `.fpp` extension (Fypp templates)
14+
and are transpiled to `.f90` during the CMake build. A minority of modules
15+
remain as plain `.f90`. The code lives in `src/`, tests in `tests/`,
16+
and example input cases in `examples/`.
17+
18+
- Fypp helper macros live in files under any `include/` directory within
19+
`src/` (e.g., `src/<module>/include/`). **Scan these macro files first** so
20+
that template expansions resolve correctly.
21+
22+
- Always assume free-form Fortran 2008+ (`.fpp` and `.f90`) with `implicit none`,
23+
explicit `intent(in|out|inout)`, and modern constructs (`allocate`,
24+
`move_alloc`, `iso_fortran_env`, etc.).
25+
26+
- Prefer `module` + `contains` → `subroutine foo()` patterns; avoid COMMON
27+
blocks and `include` files.
28+
29+
- **Simulation kernels are accelerated exclusively with OpenACC.** Always
30+
include the appropriate `!$acc` pragmas when generating or modifying
31+
performance-critical loops.
32+
33+
- **The codebase is written in Fortran 2008+ with the Fypp pre-processor.**
34+
Always use the appropriate Fypp macros when generating or modifying
35+
performance-critical loops.
36+
37+
- **Before suggesting or applying any source-code changes, first read/parse the
38+
full codebase *and* the documentation sources listed below, then produce a
39+
concise description of how the codebase is structured and functions.**
40+
41+
- Documentation sources:
42+
- Primary online docs: <https://mflowcode.github.io/documentation/md_readme.html>
43+
- Root-level `README.md` in the repository.
44+
45+
### ───────────────────────────────────────────────────────────────────
46+
### 2. Style & naming conventions (AUTO-ATTACH for *.fpp and *.f90 files)
47+
### ───────────────────────────────────────────────────────────────────
48+
49+
- Indent 2 spaces; continuation lines line up under “&”.
50+
- No maximum line length is enforced.
51+
- Prefer shorter, streamlined code—avoid needless verbosity while keeping clarity.
52+
- Lower-case keywords (`do`, `end subroutine`, etc.).
53+
- Module names: `m_<feature>` (e.g., `m_transport`).
54+
- Public procedures: `<verb>_<noun>` (e.g., `compute_flux`) with prefixe `s_` or `f_` for subroutines and functions, respectively.
55+
- Avoid private helper functions within a subroutine or function, and instead make them private to the module (if appropriate)
56+
- Helper functions or subroutines start with with f_[name here] or s_[name here], respectively
57+
- 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.
58+
- Avoid common Fortran code smells, such as:
59+
- Use of `goto` statements (except in legacy interop situations).
60+
- Omission of `intent(...)` declarations.
61+
- Use of global state via `COMMON` blocks or `save` variables.
62+
- Shadowing of variable names (especially loop indices).
63+
- Non-descriptive or single-letter variable names outside small scopes.
64+
- Excessively long helper procedures (>200 lines); prefer decomposition.
65+
- Excessively long subroutines (>500 lines); prefer decomposition.
66+
- Excessively long functions (>100 lines); prefer decomposition.
67+
- Excessively long modules (>1000 lines); prefer decomposition.
68+
- Excessively long files (>1000 lines); prefer decomposition.
69+
- Subroutines and functions that are too long to be understood at a glance.
70+
- Use of `!$acc routine seq` to mark subroutines and functions that are called from OpenACC parallel loops.
71+
- Mixing I/O logic with computation (separate concerns).
72+
- Missing implicit none statements.
73+
- Missing `intent(in|out|inout)` declarations.
74+
- Missing `dimension` or `allocatable`/`pointer` attributes.
75+
- Missing `private` declarations.
76+
- Missing `public` declarations.
77+
- Missing `module procedure` declarations.
78+
- Missing `use` statements.
79+
- Declaring arrays without `dimension` or `allocatable`/`pointer` attributes.
80+
- Use of `stop` for error handling (prefer use of the subroutine `s_mpi_abort` with an appropriate string message argument).
81+
82+
### ───────────────────────────────────────────────────────────────────
83+
### 3. Test workflow (AUTOMATICALLY applied when the code is significantly changed and should be tested)
84+
### ───────────────────────────────────────────────────────────────────
85+
86+
- Run the test suite after any meaningful code change to verify correctness.
87+
- Ask the user to alter the test suite command so that only the relevant tests are run.
88+
- When you think you are done with the code changes, run ./mfc.sh test -j $(nproc) -f EA8FA07E -t 9E2CA336
89+
- Otherwise, only run specific tests that are relevant to the code changes.
90+
- Do not run ./mfc.sh test -j $(nproc) without any other arguments (it takes too long to run all tests).
91+
92+
### ───────────────────────────────────────────────────────────────────
93+
### 4. OpenACC programming guidelines (AUTOMATICALLY applied to *.fpp/*.f90)
94+
### ───────────────────────────────────────────────────────────────────
95+
96+
- **Prefer:**
97+
98+
!$acc parallel loop gang vector default(present)
99+
100+
around tight loops over cells or particles; fall back to `!$acc kernels`
101+
only when loop dependencies prevent direct parallelization. Always add
102+
`reduction` clauses where needed.
103+
104+
- Use `collapse(n)` in `!$acc parallel loop` pragmas to combine nested loops
105+
when it improves parallelism and the iterations are independent.
106+
107+
- Use `private(var1, var2, ...)` clauses for all variables that are local
108+
to a parallel region or loop, especially scalar temporaries and loop counters.
109+
110+
- Use `!$acc routine seq` to mark subroutines and functions that are called from OpenACC parallel loops.
111+
112+
- When adding `!$acc routine seq` put it on the first line after the declaration of the subroutine or function.
113+
114+
- Allocate large arrays with the `managed` attribute or move them to the device
115+
at program start using a persistent `!$acc enter data` region.
116+
117+
- 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.
118+
119+
- Ensure the code compiles with Cray Fortran (`ftn`) and NVIDIA HPC SDK
120+
(`nvfortran`) for OpenACC GPU offloading, and with GNU (`gfortran`) and Intel
121+
(`ifx`/`ifort`) for CPU-only builds where OpenACC directives are ignored.
122+
123+
######################################################################
124+
# End of file
125+
######################################################################

0 commit comments

Comments
 (0)