Skip to content

Commit 6f4294c

Browse files
authored
Merge branch 'master' into fix/restart-grid-mismatch
2 parents 731dd59 + dc0aec1 commit 6f4294c

8 files changed

Lines changed: 34 additions & 22 deletions

File tree

.claude/CLAUDE.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
* New branches cannot be made on MFlowCode/MFC, they are made on forks
22
* PRs:
3-
* made using AI tools like Claude Code and Codex should say so.
3+
* made using AI tools like Claude Code and Codex should say so.
44
* are made from those MFC forks
5-
* that change CFD result need verification PR is correct
5+
* that change CFD results need verification that the PR is correct
66
* follow template
77
* that break a feature but promise a followup PR to fix it are rejected
88
* Commands:
@@ -11,5 +11,5 @@
1111
* Programming and Design:
1212
* New code should follow the DRY principle and also make side-effect code DRY as well
1313
* Comments should be as short as possible without sacrificing value
14-
* GPU macros should follow existing the source's GPU macro principles and patterns
15-
* Functions/subroutines/modules shorter is better while being correctness, fast, and separating concerns
14+
* GPU macros should follow the source's existing GPU macro principles and patterns
15+
* Functions/subroutines/modules shorter is better while being correct, fast, and separating concerns

.github/scripts/preflight.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ fi
5757
# microarchitecture dies with SIGILL, which would be reported as a bad node and
5858
# get a perfectly healthy one excluded.
5959
newest_syscheck() {
60-
find "$@" -name syscheck -type f -printf '%T@ %p\n' 2>/dev/null \
61-
| sort -rn | head -1 | cut -d' ' -f2-
60+
# ls -t rather than find -printf: -printf is GNU-only, and on a BSD find it
61+
# fails into 2>/dev/null, so discovery silently returns nothing and every
62+
# probe is skipped as "no syscheck binary".
63+
find "$@" -name syscheck -type f -exec ls -t {} + 2>/dev/null | head -1
6264
}
6365

6466
syscheck_bin=$(newest_syscheck build/install -path "*${device}*")
@@ -132,7 +134,9 @@ run_probe() {
132134
fi
133135
}
134136

135-
run_probe "${launcher[@]}"
137+
# ${arr[@]+"${arr[@]}"} rather than "${arr[@]}": under set -u, bash 3.2 (which is
138+
# what macOS ships) treats an empty array expansion as an unbound variable.
139+
run_probe ${launcher[@]+"${launcher[@]}"}
136140

137141
# If this launcher does not take the flags we added, drop them and probe again
138142
# rather than reporting a verdict about the node. Otherwise a launcher that

.github/workflows/homebrew-release.yml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
name: Update Homebrew Formula on Release
22

3-
# Triggers when a new version tag is pushed
3+
# Triggers when a release is published. Not `push: tags`, which GitHub skips
4+
# when the tagged commit message carries [skip ci] -- that silently dropped the
5+
# v5.6.0 and v5.7.0 formula updates, while docker.yml fired for both because a
6+
# release event is not a push event.
47
on:
5-
push:
6-
tags:
7-
- 'v*'
8+
release:
9+
types: [published]
810
pull_request:
911
branches: [master]
1012
paths:
@@ -28,6 +30,9 @@ permissions:
2830
jobs:
2931
update-homebrew-tap:
3032
name: Update homebrew-mfc tap
33+
# A prerelease tag (v5.8.0-rc1) would fail the X.Y.Z check below, so skip it
34+
# rather than reporting a red release job.
35+
if: ${{ github.event_name != 'release' || !github.event.release.prerelease }}
3136
runs-on: ubuntu-latest
3237
environment:
3338
name: homebrew
@@ -44,8 +49,9 @@ jobs:
4449
VERSION="5.2.0"
4550
echo "::notice::PR test mode - using version $VERSION"
4651
else
47-
# Extract version from tag (remove 'v' prefix)
48-
VERSION="${GITHUB_REF#refs/tags/v}"
52+
# Extract version from the released tag (remove 'v' prefix)
53+
VERSION="${{ github.event.release.tag_name }}"
54+
VERSION="${VERSION#v}"
4955
fi
5056
5157
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
@@ -97,7 +103,7 @@ jobs:
97103
echo "- Update formula" >> $GITHUB_STEP_SUMMARY
98104
echo "- Push to tap" >> $GITHUB_STEP_SUMMARY
99105
echo "" >> $GITHUB_STEP_SUMMARY
100-
echo "The full workflow will run when a \`v*\` tag is pushed after merge." >> $GITHUB_STEP_SUMMARY
106+
echo "The full workflow will run when a release is published after merge." >> $GITHUB_STEP_SUMMARY
101107
102108
- name: Checkout homebrew-mfc tap
103109
if: ${{ github.event_name != 'pull_request' }}

docs/documentation/contributing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ Both human reviewers and AI code reviewers reference this section.
217217

218218
### Parameter Plumbing
219219

220-
- **Derived-type parameters are not auto-broadcast.** `generated_bcast.fpp` covers namelist *scalars* only. Each derived type (`chem_params`, `lag_params`, `rburn`) needs a hand-written `_emit_<name>` in `toolchain/mfc/params/generators/fortran_gen.py` plus its call site in that generator's simulation branch, and, if it is read on device, an explicit `$:GPU_UPDATE(device='[name]')` in both the target's `m_global_parameters.fpp` and `src/simulation/m_start_up.fpp``GPU_DECLARE` alone does not make it device-resident. Regrouping existing scalars into a derived type silently drops their broadcast, leaving every non-root rank holding the `dflt_real` sentinel. Single-rank golden files cannot catch this, so pair such a change with a `ppn=2` test and confirm it fails without the emitter.
220+
- **Derived-type parameters are not auto-broadcast.** `generated_bcast.fpp` covers namelist *scalars* only. Each derived type (`chem_params`, `lag_params`, `rburn`) needs a hand-written `_emit_<name>` in `toolchain/mfc/params/generators/fortran_gen.py` plus its call site in that generator's simulation branch, and, if it is read on device, an explicit ``$:GPU_UPDATE(device='[name]')`` in both the target's `m_global_parameters.fpp` and `src/simulation/m_start_up.fpp``GPU_DECLARE` alone does not make it device-resident. Regrouping existing scalars into a derived type silently drops their broadcast, leaving every non-root rank holding the `dflt_real` sentinel. Single-rank golden files cannot catch this, so pair such a change with a `ppn=2` test and confirm it fails without the emitter.
221221
- **A `patch_ib` member that immersed-boundary ghost-point code reads must also be set in `s_add_cloud_particle`** (`src/simulation/m_particle_cloud.fpp`). `particle_cloud_ibs` is allocated without default initialization, and `s_reduce_ib_patch_array` copies the whole struct into `patch_ib`, overwriting the defaults assigned in `s_assign_default_values_to_user_inputs`. Anything left unset reaches the solver as uninitialized memory, and only where the allocation is not already zero-filled. A platform-only NaN is the signature of this class: a garbage `v_blow` once failed an AMD lane with `ICFL is NaN` while every NVIDIA lane and all local runs passed.
222222
- **Runtime checks go where they run.** Shared constraints belong in `src/common/m_checker_common.fpp`, simulation-only ones in `src/simulation/m_checker.fpp`, and pre- and post-process ones in their own `m_checker.fpp`. Those two `s_check_inputs` are currently empty; that is still the correct home for their checks, not `m_checker_common`.
223223
- **Analytic initial conditions are compiled into the binary** and their expressions are AST-validated at case load, so syntax errors and unknown variables surface immediately and by name. Each IC variable maps to an `eqn_idx` expression in `QPVF_IDX_VARS` (`toolchain/mfc/case.py`); adding a patch-settable conserved variable means updating that map and the Fortran `eqn_idx` builder together, because a mismatch is a silent wrong index.

docs/documentation/gpuParallelization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ while the host still registers it. The first launch aborts with
864864
followed by a segmentation fault. Never place a GPU kernel inside a `block` construct;
865865
hoist it into its own (module) subroutine with the locals passed as arguments.
866866

867-
## Silent-Failure Traps
867+
## Silent-Failure Traps {#silent-failure-traps}
868868

869869
Every entry here was measured. They share a failure mode: the build stays green and the
870870
answer is wrong, or one backend diverges from all the others.
@@ -874,7 +874,7 @@ answer is wrong, or one backend diverges from all the others.
874874
always use `GPU_PARALLEL_LOOP` / `END_GPU_PARALLEL_LOOP`.
875875
- **An array whose bound is a device global** (`dimension(num_fluids)`,
876876
`dimension(num_species)`) may be passed to a device routine from a parallel-loop body,
877-
but **not from inside another `GPU_ROUTINE(parallelism='[seq]')`**. Cray OpenACC rejects
877+
but **not from inside another ``GPU_ROUTINE(parallelism='[seq]')``**. Cray OpenACC rejects
878878
the second form with `ftn-7066 ... Global in accelerator routine without declare`, and
879879
reports it at whatever line it gave up on: remove one trigger and the message walks
880880
forward to the next call, so the reported line is not the cause. Only the plain lanes

docs/documentation/testing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ If a trace is empty (that is, the empty string `""`), it will not appear in the
9292

9393
Finally, the case is appended to the `cases` list, which will be returned by the `list_cases` function.
9494

95-
### Selection and Execution Pitfalls
95+
### Selection and Execution Pitfalls {#selection-and-execution-pitfalls}
9696

9797
Each of these fails quietly rather than loudly.
9898

toolchain/mfc/lint_source.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,10 @@ def check_device_routine_element_args(repo_root: Path) -> list[str]:
629629
routine containing any `GPU_LOOP`, called with an array element as an actual argument, reads
630630
the element as garbage and never writes it back. Either alone is fine, every `routine` level
631631
is affected, and the loop counts when it sits in anything the routine calls. Copy the element
632-
to a scalar before the call and receive results into a scalar. See
633-
sbryngelson/compiler-bugs cce/acc-routine-element-by-reference.
632+
to a scalar before the call and receive results into a scalar. See the Silent-Failure
633+
Traps section of docs/documentation/gpuParallelization.md, MFC issue
634+
https://github.com/MFlowCode/MFC/issues/1815, and the reproducer at
635+
https://github.com/sbryngelson/compiler-bugs/tree/main/cce/acc-routine-element-by-reference.
634636
"""
635637
src_dir = repo_root / SRC_DIR
636638
files = {src: src.read_text(encoding="utf-8").splitlines() for src in _fortran_fpp_files(src_dir)}
@@ -683,7 +685,7 @@ def check_device_routine_element_args(repo_root: Path) -> list[str]:
683685
for arg in _split_top_level(stmt[m.end() : j - 1]):
684686
e = _ELEMENT_ARG.match(arg)
685687
if e and ":" not in arg and not _VALUE_CALL_NAMES.match(e.group(1)):
686-
errors.append(f" {rel}:{line_no} `{arg}` into `{name}` (a device routine with a seq loop): pass a scalar, see sbryngelson/compiler-bugs cce/acc-routine-element-by-reference")
688+
errors.append(f" {rel}:{line_no} `{arg}` into `{name}` (a device routine with a seq loop): pass a scalar, see docs/documentation/gpuParallelization.md (Silent-Failure Traps)")
687689
return errors
688690

689691

toolchain/mfc/test_preflight.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def workspace(tmp_path):
4444
# stand in for a launcher the test meant to be absent.
4545
sysbin = tmp_path / "sysbin"
4646
sysbin.mkdir()
47-
for tool in ("bash", "find", "head", "tail", "cat", "sed", "grep", "tr", "cut", "date", "mkdir", "mv", "rm", "hostname", "env", "sort", "wc", "dirname", "basename"):
47+
for tool in ("bash", "find", "head", "tail", "cat", "sed", "grep", "tr", "cut", "date", "mkdir", "mv", "rm", "hostname", "env", "sort", "wc", "dirname", "basename", "ls"):
4848
for root in ("/usr/bin", "/bin"):
4949
src = Path(root) / tool
5050
if src.exists():

0 commit comments

Comments
 (0)