1- ----
2- - description: Full MFC project rules – consolidated for Agent Mode
3- - alwaysApply: true
4- ----
1+ ---
2+ description: Full MFC project rules – consolidated for Agent Mode
3+ alwaysApply: true
4+ ---
55
66# 0 Purpose & Scope
7- Consolidated guidance for the MFC exascale, many-physics solver.
8- Written primarily for Fortran/Fypp; the GPU and style sections matter only when `.fpp` / `.f90` files are in view.
7+ Consolidated guidance for the MFC exascale, many-physics solver.
8+ Written primarily for Fortran/Fypp; the OpenACC and style sections matter only when
9+ `.fpp` / `.f90` files are in view.
910
1011---
1112
1213# 1 Global Project Context (always)
13- - **Project**: *MFC* is modern Fortran 2008+ generated with **Fypp**.
14- - Sources `src/`, tests `tests/`, examples `examples/`.
15- - Most sources are `.fpp`; CMake transpiles them to `.f90`.
16- - **Fypp macros** live in `src/<subprogram>/include/` you should scan these first.
17- `<subprogram>` ∈ {`simulation`,`common`,`pre_process`,`post_process`}.
18- - Only `simulation` (+ its `common` calls) is GPU-accelerated via **OpenACC** or **OpenMP**.
19- - Assume free-form Fortran 2008+, `implicit none`, explicit `intent`, and modern intrinsics.
20- - Prefer `module … contains … subroutine foo()`; avoid `COMMON` blocks and file-level `include` files.
21- - **Read the full codebase and docs *before* changing code.**
22- - Docs: <https://mflowcode.github.io/documentation/md_readme.html> and the respository root `README.md`.
14+ - **Project**: *MFC* is modern Fortran 2008+ generated with **Fypp**.
15+ - Sources `src/`, tests `tests/`, examples `examples/`.
16+ - Most sources are `.fpp`; CMake transpiles them to `.f90`.
17+ - **Fypp macros** live in `src/<subprogram>/include/` you should scan these first.
18+ `<subprogram>` ∈ {`simulation`,`common`,`pre_process`,`post_process`}.
19+ - Only `simulation` (+ its `common` calls) is GPU-accelerated via **OpenACC** or **OpenMP**.
20+ - Assume free-form Fortran 2008+, `implicit none`, explicit `intent`, and modern
21+ intrinsics.
22+ - Prefer `module … contains … subroutine foo()`; avoid `COMMON` blocks and
23+ file-level `include` files.
24+ - **Read the full codebase and docs *before* changing code.**
25+ Docs: <https://mflowcode.github.io/documentation/md_readme.html> and the respository root `README.md`.
2326
2427### Incremental-change workflow
25-
26- 1. Draft a step-by-step plan.
27- 2. After each step, build:
28+ 1. Draft a step-by-step plan.
29+ 2. After each step, build:
2830 ```bash
2931 ./mfc.sh build -t pre_process simulation -j $(nproc)
3032 ```
@@ -47,10 +49,12 @@ Written primarily for Fortran/Fypp; the GPU and style sections matter only when
4749 * Subroutine → `s_<verb>_<noun>` (e.g. `s_compute_flux`)
4850 * Function → `f_<verb>_<noun>`
4951* Private helpers stay in the module; avoid nested procedures.
50- * **Size limits**: subroutine ≤ 500 lines, helper ≤ 150, function ≤ 100, module/file ≤ 1000.
51- * ≤ 6 arguments per routine; otherwise pass a derived-type "params" struct.
52+ * **Size limits**: subroutine ≤ 500 lines, helper ≤ 150, function ≤ 100,
53+ module/file ≤ 1000.
54+ * ≤ 6 arguments per routine; otherwise pass a derived-type “params” struct.
5255* No `goto` (except unavoidable legacy); no global state (`COMMON`, `save`).
53- * Every variable: `intent(in|out|inout)` + appropriate `dimension` / `allocatable` / `pointer`.
56+ * Every variable: `intent(in|out|inout)` + appropriate `dimension` / `allocatable`
57+ / `pointer`.
5458* Use `s_mpi_abort(<msg>)` for errors, not `stop`.
5559* Mark GPU-callable helpers that are called from GPU parallel loops immediately after declaration:
5660 ```fortran
@@ -62,10 +66,9 @@ Written primarily for Fortran/Fypp; the GPU and style sections matter only when
6266
6367---
6468
65- # 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for GPU kernels)
69+ # 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for kernels)
6670
67- Do not directly use OpenACC or OpenMP directives directly.
68- Instead, use the FYPP macros contained in src/common/include/parallel_macros.fpp
71+ Do not directly use OpenACC or OpenMP directives directly. Instead, use the FYPP macros contained in src/common/include/parallel_macros.fpp
6972
7073Wrap tight loops with
7174
@@ -79,100 +82,3 @@ $:GPU_PARALLEL_FOR(private='[...]', copy='[...]')
7982* **Do not** place `stop` / `error stop` inside device code.
8083* Must compile with Cray `ftn` and NVIDIA `nvfortran` for GPU offloading; also build CPU-only with
8184 GNU `gfortran` and Intel `ifx`/`ifort`.
82-
83- ---
84-
85- # 4 File & Module Structure
86-
87- - **File Naming**:
88- - `.fpp` files: Fypp preprocessed files that get translated to `.f90`
89- - Modules are named with `m_` prefix followed by feature name: `m_helper_basic`, `m_viscous`
90- - Primary program file is named `p_main.fpp`
91-
92- - **Module Layout**:
93- - Start with Fypp include for macros: `#:include 'macros.fpp'`
94- - Header comments using `!>` style documentation
95- - `module` declaration with name matching filename
96- - `use` statements for dependencies
97- - `implicit none` statement
98- - `private` declaration followed by explicit `public` exports
99- - `contains` section
100- - Implementation of subroutines and functions
101-
102- # 5 Fypp Macros and GPU Acceleration
103-
104- ## Use of Fypp
105- - **Fypp Directives**:
106- - Start with `#:` (e.g., `#:include`, `#:def`, `#:enddef`)
107- - Macros defined in `include/*.fpp` files
108- - Used for code generation, conditional compilation, and GPU offloading
109-
110- ## Some examples
111-
112- Documentation on how to use the Fypp macros for GPU offloading is available at https://mflowcode.github.io/documentation/md_gpuParallelization.html
113-
114- Some examples include:
115- - `$:GPU_ROUTINE(parallelism='[seq]')` - Marks GPU-callable routines
116- - `$:GPU_PARALLEL_LOOP(collapse=N)` - Parallelizes loops
117- - `$:GPU_LOOP(parallelism='[seq]')` - Marks sequential loops
118- - `$:GPU_UPDATE(device='[var1,var2]')` - Updates device data
119- - `$:GPU_ENTER_DATA(copyin='[var]')` - Copies data to device
120- - `$:GPU_EXIT_DATA(delete='[var]')` - Removes data from device
121-
122- # 6 Documentation Style
123-
124- - **Subroutine/Function Documentation**:
125- ```fortran
126- !> This procedure <description>
127- !! @param param_name Description of the parameter
128- !! @return Description of the return value (for functions)
129- ```
130- which conforms to the Doxygen Fortran format.
131-
132- # 7 Error Handling
133-
134- - **Assertions**:
135- - Use the fypp `ASSERT` macro for validating conditions
136- - Example: `@:ASSERT(predicate, message)`
137-
138- - **Error Reporting**:
139- - Use `s_mpi_abort(<msg>)` for error termination, not `stop`
140- - No `stop` / `error stop` inside device code
141-
142- # 8 Memory Management
143-
144- - **Allocation/Deallocation**:
145- - Use fypp macro `@:ALLOCATE(var1, var2)` macro for device-aware allocation
146- - Use fypp macro `@:DEALLOCATE(var1, var2)` macro for device-aware deallocation
147-
148- # 9. Additional Observed Patterns
149-
150- - **Derived Types**:
151- - Extensive use of derived types for encapsulation
152- - Use pointers within derived types (e.g., `pointer, dimension(:,:,:) => null()`)
153- - Clear documentation of derived type components
154-
155- - **Pure & Elemental Functions**:
156- - Use `pure` and `elemental` attributes for side-effect-free functions
157- - Combine them for operations on arrays (`pure elemental function`)
158-
159- - **Precision Handling**:
160- - Use `wp` (working precision) parameter from `m_precision_select`
161- - Never hardcode precision with `real*8` or similar
162-
163- - **Loop Optimization**:
164- - Favor array operations over explicit loops when possible
165- - Use `collapse=N` directive to optimize nested loops
166-
167- # 10. Fortran Practices to Avoid
168-
169- - **Fixed Format**: Only free-form Fortran is used
170- - No column-position dependent code
171-
172- - **Older Intrinsics**: Avoid outdated Fortran features like:
173- - `equivalence` statements
174- - `data` statements (use initialization expressions)
175- - Character*N (use `character(len=N)` instead)
176-
177- - **Using same variable for multiple purposes**: Maintain single responsibility
178- - Each variable should have one clear purpose
0 commit comments