Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 28 additions & 122 deletions .cursor/rules/mfc-agent-rules.mdc
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
----
-description: Full MFC project rules – consolidated for Agent Mode
-alwaysApply: true
----
---
description: Full MFC project rules – consolidated for Agent Mode
alwaysApply: true
---

# 0 Purpose & Scope
Consolidated guidance for the MFC exascale, many-physics solver.
Written primarily for Fortran/Fypp; the GPU and style sections matter only when `.fpp` / `.f90` files are in view.
Consolidated guidance for the MFC exascale, many-physics solver.
Written primarily for Fortran/Fypp; the OpenACC and style sections matter only when
`.fpp` / `.f90` files are in view.

---

# 1 Global Project Context (always)
- **Project**: *MFC* is modern Fortran 2008+ generated with **Fypp**.
- Sources `src/`, tests `tests/`, examples `examples/`.
- Most sources are `.fpp`; CMake transpiles them to `.f90`.
- **Fypp macros** live in `src/<subprogram>/include/` you should scan these first.
`<subprogram>` ∈ {`simulation`,`common`,`pre_process`,`post_process`}.
- Only `simulation` (+ its `common` calls) is GPU-accelerated via **OpenACC** or **OpenMP**.
- Assume free-form Fortran 2008+, `implicit none`, explicit `intent`, and modern intrinsics.
- Prefer `module … contains … subroutine foo()`; avoid `COMMON` blocks and file-level `include` files.
- **Read the full codebase and docs *before* changing code.**
- Docs: <https://mflowcode.github.io/documentation/md_readme.html> and the respository root `README.md`.
- **Project**: *MFC* is modern Fortran 2008+ generated with **Fypp**.
- Sources `src/`, tests `tests/`, examples `examples/`.
- Most sources are `.fpp`; CMake transpiles them to `.f90`.
- **Fypp macros** live in `src/<subprogram>/include/` you should scan these first.
`<subprogram>` ∈ {`simulation`,`common`,`pre_process`,`post_process`}.
- Only `simulation` (+ its `common` calls) is GPU-accelerated via **OpenACC** or **OpenMP**.
- Assume free-form Fortran 2008+, `implicit none`, explicit `intent`, and modern
intrinsics.
- Prefer `module … contains … subroutine foo()`; avoid `COMMON` blocks and
file-level `include` files.
- **Read the full codebase and docs *before* changing code.**
Docs: <https://mflowcode.github.io/documentation/md_readme.html> and the respository root `README.md`.

### Incremental-change workflow

1. Draft a step-by-step plan.
2. After each step, build:
1. Draft a step-by-step plan.
2. After each step, build:
```bash
./mfc.sh build -t pre_process simulation -j $(nproc)
```
Expand All @@ -47,10 +49,12 @@ Written primarily for Fortran/Fypp; the GPU and style sections matter only when
* Subroutine → `s_<verb>_<noun>` (e.g. `s_compute_flux`)
* Function → `f_<verb>_<noun>`
* Private helpers stay in the module; avoid nested procedures.
* **Size limits**: subroutine ≤ 500 lines, helper ≤ 150, function ≤ 100, module/file ≤ 1000.
* ≤ 6 arguments per routine; otherwise pass a derived-type "params" struct.
* **Size limits**: subroutine ≤ 500 lines, helper ≤ 150, function ≤ 100,
module/file ≤ 1000.
* ≤ 6 arguments per routine; otherwise pass a derived-type “params” struct.
* No `goto` (except unavoidable legacy); no global state (`COMMON`, `save`).
* Every variable: `intent(in|out|inout)` + appropriate `dimension` / `allocatable` / `pointer`.
* Every variable: `intent(in|out|inout)` + appropriate `dimension` / `allocatable`
/ `pointer`.
* Use `s_mpi_abort(<msg>)` for errors, not `stop`.
* Mark GPU-callable helpers that are called from GPU parallel loops immediately after declaration:
```fortran
Expand All @@ -62,10 +66,9 @@ Written primarily for Fortran/Fypp; the GPU and style sections matter only when

---

# 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for GPU kernels)
# 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for kernels)
Copy link
Preview

Copilot AI Jul 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a spelling error in 'Pogramming' which should be 'Programming'.

Suggested change
# 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for kernels)
# 3 FYPP Macros for GPU acceleration Programming Guidelines (for kernels)

Copilot uses AI. Check for mistakes.


Do not directly use OpenACC or OpenMP directives directly.
Instead, use the FYPP macros contained in src/common/include/parallel_macros.fpp
Do not directly use OpenACC or OpenMP directives directly. Instead, use the FYPP macros contained in src/common/include/parallel_macros.fpp

Wrap tight loops with

Expand All @@ -79,100 +82,3 @@ $:GPU_PARALLEL_FOR(private='[...]', copy='[...]')
* **Do not** place `stop` / `error stop` inside device code.
* Must compile with Cray `ftn` and NVIDIA `nvfortran` for GPU offloading; also build CPU-only with
GNU `gfortran` and Intel `ifx`/`ifort`.

---

# 4 File & Module Structure

- **File Naming**:
- `.fpp` files: Fypp preprocessed files that get translated to `.f90`
- Modules are named with `m_` prefix followed by feature name: `m_helper_basic`, `m_viscous`
- Primary program file is named `p_main.fpp`

- **Module Layout**:
- Start with Fypp include for macros: `#:include 'macros.fpp'`
- Header comments using `!>` style documentation
- `module` declaration with name matching filename
- `use` statements for dependencies
- `implicit none` statement
- `private` declaration followed by explicit `public` exports
- `contains` section
- Implementation of subroutines and functions

# 5 Fypp Macros and GPU Acceleration

## Use of Fypp
- **Fypp Directives**:
- Start with `#:` (e.g., `#:include`, `#:def`, `#:enddef`)
- Macros defined in `include/*.fpp` files
- Used for code generation, conditional compilation, and GPU offloading

## Some examples

Documentation on how to use the Fypp macros for GPU offloading is available at https://mflowcode.github.io/documentation/md_gpuParallelization.html

Some examples include:
- `$:GPU_ROUTINE(parallelism='[seq]')` - Marks GPU-callable routines
- `$:GPU_PARALLEL_LOOP(collapse=N)` - Parallelizes loops
- `$:GPU_LOOP(parallelism='[seq]')` - Marks sequential loops
- `$:GPU_UPDATE(device='[var1,var2]')` - Updates device data
- `$:GPU_ENTER_DATA(copyin='[var]')` - Copies data to device
- `$:GPU_EXIT_DATA(delete='[var]')` - Removes data from device

# 6 Documentation Style

- **Subroutine/Function Documentation**:
```fortran
!> This procedure <description>
!! @param param_name Description of the parameter
!! @return Description of the return value (for functions)
```
which conforms to the Doxygen Fortran format.

# 7 Error Handling

- **Assertions**:
- Use the fypp `ASSERT` macro for validating conditions
- Example: `@:ASSERT(predicate, message)`

- **Error Reporting**:
- Use `s_mpi_abort(<msg>)` for error termination, not `stop`
- No `stop` / `error stop` inside device code

# 8 Memory Management

- **Allocation/Deallocation**:
- Use fypp macro `@:ALLOCATE(var1, var2)` macro for device-aware allocation
- Use fypp macro `@:DEALLOCATE(var1, var2)` macro for device-aware deallocation

# 9. Additional Observed Patterns

- **Derived Types**:
- Extensive use of derived types for encapsulation
- Use pointers within derived types (e.g., `pointer, dimension(:,:,:) => null()`)
- Clear documentation of derived type components

- **Pure & Elemental Functions**:
- Use `pure` and `elemental` attributes for side-effect-free functions
- Combine them for operations on arrays (`pure elemental function`)

- **Precision Handling**:
- Use `wp` (working precision) parameter from `m_precision_select`
- Never hardcode precision with `real*8` or similar

- **Loop Optimization**:
- Favor array operations over explicit loops when possible
- Use `collapse=N` directive to optimize nested loops

# 10. Fortran Practices to Avoid

- **Fixed Format**: Only free-form Fortran is used
- No column-position dependent code

- **Older Intrinsics**: Avoid outdated Fortran features like:
- `equivalence` statements
- `data` statements (use initialization expressions)
- Character*N (use `character(len=N)` instead)

- **Using same variable for multiple purposes**: Maintain single responsibility
- Each variable should have one clear purpose