Skip to content

1687 fix: Make OpenMP no_create a documented no-op instead of aborting fypp. - #1724

Open
engineer-scientist wants to merge 3 commits into
MFlowCode:masterfrom
engineer-scientist:claude/mflowcode-issue-1687-yic86y
Open

1687 fix: Make OpenMP no_create a documented no-op instead of aborting fypp.#1724
engineer-scientist wants to merge 3 commits into
MFlowCode:masterfrom
engineer-scientist:claude/mflowcode-issue-1687-yic86y

Conversation

@engineer-scientist

Copy link
Copy Markdown
Contributor

OMP_NOCREATE_STR called #:stop whenever no_create was set. GPU_PARALLEL, GPU_PARALLEL_LOOP and GPU_DATA expand both the ACC and OMP directive strings at fypp time and let the compile-time #if select one, so the abort fired on OpenACC-only builds too -- making a documented parameter unusable on every backend.

OpenMP has no no_create equivalent, and OMP_DEFAULT_STR already emits a present-by-default mapping, so emitting nothing is the closest safe behavior. Document the clause as OpenACC-only, matching the existing GPU_CACHE note.

Generated Fortran is byte-identical across all 109 .fpp files in the three targets: every call site passes no_create=None, which already took the empty-string path.

Closes #1687

Claude-Session: https://claude.ai/code/session_016xc51kikzrKdHDfXf8VV5p

Description

OMP_NOCREATE_STR called #:stop 'no_create is not supported yet' whenever no_create was non-None. Because GPU_PARALLEL, GPU_PARALLEL_LOOP and GPU_DATA build both the ACC and OMP directive strings with #:set and then let the compile-time #if defined(MFC_OpenACC) / #elif defined(MFC_OpenMP) pick one, that #:stop fired during fypp preprocessing on OpenACC-only builds too — making a documented public parameter unusable on every backend, with an error pointing into omp_macros.fpp rather than at the caller.
This takes option (1) from the issue: the OpenMP path becomes a documented no-op, and the working OpenACC implementation (GEN_NOCREATE_STR) stays reachable.
Worth noting for context: MFC_OpenACC / MFC_OpenMP are never passed to fypp — cmake/Fypp.cmake only defines MFC_<CompilerId>, MFC_<TARGET>, MFC_COMPILER, MFC_CASE_OPTIMIZATION and chemistry. So fypp cannot know which backend will survive, and expanding both is structural rather than incidental. The invariant that follows is that every clause helper must be evaluable for every build; a #:stop in one backend's helper is an unconditional abort, not a guard.
Emitting nothing is the closest safe behavior rather than a silent wrong answer: OpenACC's no_create asks for "use the device copy if present, otherwise the host copy, don't allocate", and OMP_DEFAULT_STR already emits defaultmap(present:allocatable) (Cray) / defaultmap(tofrom:...) — the present-by-default behavior is already ambient.
Also adds (OpenACC only) to the no_create row of the three parameter tables in gpuParallelization.md, matching the existing GPU_CACHE convention ("NOTE Does not do anything for OpenMP currently"). Without it, the fix trades a loud failure for a silent one.
The replacement comment is deliberately the same line count as the code it replaces, so fypp's # line markers don't shift and the generated Fortran stays byte-identical (see Testing).

Closes #1687.

Type of change (delete unused ones)

  • Bug fix
  • Documentation

Testing

  1. The issue's reproduction case. Same file and flags as the issue, MFC_SIMULATION only, no OpenMP anywhere:
Before: EXIT=1, omp_macros.fpp:71: error: no_create is not supported yet [FyppStopRequest]
After:  EXIT=0, !$acc parallel loop gang vector default(present) private(i) no_create(a)
  1. All three affected macros (no_create='[a]' on each):
    Macro OpenACC OpenMP
    GPU_PARALLEL !$acc parallel default(present) no_create(a) !$omp target teams defaultmap(tofrom:aggregate) …
    GPU_DATA !$acc data no_create(a) !$omp target data
    GPU_PARALLEL_LOOP !$acc parallel loop gang vector default(present) private(i) no_create(a) !$omp target teams loop … private(i)
  2. Zero blast radius — full-tree expansion is byte-identical. Since this is a header included nearly everywhere, I expanded every .fpp in the tree twice (original vs. patched omp_macros.fpp), using each target's real generated includes and the exact flag set from cmake/Fypp.cmake, and diffed the generated Fortran:
    Target Files Result
    pre_process 29 byte-identical
    simulation 57 byte-identical
    post_process 23 byte-identical
    Also repeated for chemistry=True and for --case-optimization + chemistry=True — byte-identical in every configuration.
    (Only fypp's embedded absolute source path differs between the two checkouts; normalized away.) Expected, since every call site passes no_create=None and already took the #:set no_create_val = '' path — but demonstrated rather than asserted.
  3. Standard workflow, gfortran 13.3.0, CPU, no MPI:
    ./mfc.sh format — 294 files unchanged
    ./mfc.sh precheck — 7/7 passed
    ./mfc.sh buildpre_process, simulation, post_process all build
    ./mfc.sh test — 609/611 pass. Two chemistry cases failed: 2D -> Chemistry -> Reacting Mixing Layer (C4EB58A8, tolerance) and 2D -> Chemistry -> Spatial Reacting Mixing Layer (56F8C4BC, pre_process exit 1). I don't believe these are mine, and I checked rather than assumed: both pass when run in isolation with this patch applied, and both pass on stock master. Point 3's expansion diff also holds for their exact build configuration — byte-identical under chemistry=True (29 + 57 files) and under --case-optimization + chemistry=True (39 files) — so the binaries under test are unchanged by this patch. 56F8C4BC's error is hcid=274 file has more lines than the grid: examples/2D_spatial_reacting_mixing_layer/IC/prim.1.00.000000.dat, i.e. a shared example input read against the harness's shrunken 31×31 grid, which reads like interference in the parallel full-suite run. Caveat: I did not re-run the full 41-minute suite on master to reproduce them there, so I'm flagging rather than claiming a known flake — happy to dig further if you'd like.
    I have no GPU or ACC-capable compiler, so the emitted no_create(...) syntax has not been compiled by an OpenACC compiler — though it is the same GEN_PARENTHESES_CLAUSE output as every other ACC clause here, and nothing in the tree passes no_create at runtime today.
    No test added. toolchain/mfc/test/cases.py generates end-to-end solver runs compared against golden files; there is no unit layer for macro expansion, and a no_create case would require inventing a solver call site that passes the parameter. Happy to add a fypp-expansion smoke test as new infrastructure if you'd like it, but that felt like its own PR.

Checklist

Check these like this [x] to indicate which of the below applies.

  • I added or updated tests for new behavior
  • I updated documentation if user-facing behavior changed

See the developer guide for full coding standards.

GPU changes (expand if you modified src/simulation/)
  • GPU results match CPU results
  • Tested on NVIDIA GPU or AMD GPU

Audit of the other clauses (per the issue's closing question)

You asked whether create, attach, deviceptr and present share the same trap. I checked every #:stop in the macro layer:

Clause OpenMP helper Aborts? Verdict
create OMP_CREATE_STRmap(always,alloc:) No Fine
present OMP_PRESENT_STRmap(present,alloc:) No Fine
deviceptr OMP_DEVICEPTR_STRuse_device_ptr(...) No Fine
attach mapped in OMP_PARALLEL* No Semantics questioned by #1693: left alone
default='none' OMP_DEFAULT_STR (omp_macros.fpp:36) Yes Same bug class
default is public and documented as accepting 'present' or 'none'; GEN_DEFAULT_STR handles 'none' correctly but OMP_DEFAULT_STR #:stops on it, so GPU_PARALLEL_LOOP(default='none') aborts fypp on an OpenACC-only build for exactly the same reason.
I did not fix it here. Unlike no_create, emitting nothing for default='none' would be a semantic change rather than a no-op — default(none) demands explicit data clauses, and silently dropping it would weaken a correctness check the caller asked for. Happy to open a separate issue, or to fold a fix in here if you'd prefer.
The remaining #:stops (shared_parallel_macros.fpp:32,34,92, omp_macros.fpp:262,319) all reject malformed input — unbalanced parentheses, a reduction list without an operator, a GPU_DATA wrapping no code. Those are backend-independent and correct as-is.

AI code reviews

Reviews are not retriggered automatically. To request a review, comment on the PR:

  • @claude full review — Claude full review (also triggers on PR open/reopen/ready)
  • Or add label claude-full-review — Claude full review via label

OMP_NOCREATE_STR called #:stop whenever no_create was set. GPU_PARALLEL,
GPU_PARALLEL_LOOP and GPU_DATA expand both the ACC and OMP directive
strings at fypp time and let the compile-time #if select one, so the
abort fired on OpenACC-only builds too -- making a documented parameter
unusable on every backend.

OpenMP has no no_create equivalent, and OMP_DEFAULT_STR already emits a
present-by-default mapping, so emitting nothing is the closest safe
behavior. Document the clause as OpenACC-only, matching the existing
GPU_CACHE note.

Generated Fortran is byte-identical across all 109 .fpp files in the
three targets: every call site passes no_create=None, which already took
the empty-string path.

Closes MFlowCode#1687

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016xc51kikzrKdHDfXf8VV5p
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.21%. Comparing base (ae4b4c4) to head (3a8410b).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1724   +/-   ##
=======================================
  Coverage   61.21%   61.21%           
=======================================
  Files          84       84           
  Lines       21601    21601           
  Branches     3195     3195           
=======================================
  Hits        13223    13223           
  Misses       6209     6209           
  Partials     2169     2169           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

GPU_PARALLEL_LOOP advertises no_create but OMP_NOCREATE_STR aborts fypp, breaking OpenACC-only builds

2 participants