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 OpenACC and style sections matter only when
9- `.fpp` / `.f90` files are in view.
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.
109
1110---
1211
1312# 1 Global Project Context (always)
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`.
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`.
2623
2724### Incremental-change workflow
28- 1. Draft a step-by-step plan.
29- 2. After each step, build:
25+
26+ 1. Draft a step-by-step plan.
27+ 2. After each step, build:
3028 ```bash
3129 ./mfc.sh build -t pre_process simulation -j $(nproc)
3230 ```
@@ -49,12 +47,10 @@ Written primarily for Fortran/Fypp; the OpenACC and style sections matter only w
4947 * Subroutine → `s_<verb>_<noun>` (e.g. `s_compute_flux`)
5048 * Function → `f_<verb>_<noun>`
5149* Private helpers stay in the module; avoid nested procedures.
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.
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.
5552* No `goto` (except unavoidable legacy); no global state (`COMMON`, `save`).
56- * Every variable: `intent(in|out|inout)` + appropriate `dimension` / `allocatable`
57- / `pointer`.
53+ * Every variable: `intent(in|out|inout)` + appropriate `dimension` / `allocatable` / `pointer`.
5854* Use `s_mpi_abort(<msg>)` for errors, not `stop`.
5955* Mark GPU-callable helpers that are called from GPU parallel loops immediately after declaration:
6056 ```fortran
@@ -66,9 +62,10 @@ Written primarily for Fortran/Fypp; the OpenACC and style sections matter only w
6662
6763---
6864
69- # 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for kernels)
65+ # 3 FYPP Macros for GPU acceleration Pogramming Guidelines (for GPU kernels)
7066
71- Do not directly use OpenACC or OpenMP directives directly. Instead, use the FYPP macros contained in src/common/include/parallel_macros.fpp
67+ Do not directly use OpenACC or OpenMP directives directly.
68+ Instead, use the FYPP macros contained in src/common/include/parallel_macros.fpp
7269
7370Wrap tight loops with
7471
@@ -82,3 +79,100 @@ $:GPU_PARALLEL_FOR(private='[...]', copy='[...]')
8279* **Do not** place `stop` / `error stop` inside device code.
8380* Must compile with Cray `ftn` and NVIDIA `nvfortran` for GPU offloading; also build CPU-only with
8481 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