Skip to content

Seed the Fortran reference and default to the native engine - #235

Merged
neuromechanist merged 5 commits into
mainfrom
228-seedable-fortran
Aug 16, 2026
Merged

neuromechanist merged 5 commits into
mainfrom
228-seedable-fortran

Conversation

@neuromechanist

Copy link
Copy Markdown
Member

Makes the Fortran reference reproducible, which #228 assumed impossible. Follows #233 (merged). Replaces PR #234, which GitHub auto-closed when its base branch was deleted.

We already had the fix, just not in the tracked source

sccn/amica PR #54 — portable + seedable random_seed — has been applied at build time by native/patch_sources.py since epic #165, with the tracked amica15.f90 deliberately left as a read-only mirror of upstream master. Upstream has not merged #54, so the reference we validate against has been the unseeded one.

Per maintainer direction, pamica now carries #54 in its own source rather than waiting: an unseedable reference cannot anchor a parity gate, so mirroring upstream costs more than it buys. The patch script keeps working on an unpatched upstream source and is now normally a no-op.

Measured

Bundled sample, 50 iterations, two runs each:

configuration max abs diff in W
legacy amica15mac, unseeded 0.42 – 0.59
native build + seed 42 3.3e-05
native build + seed 42 + max_threads 1 0.0

Seeding pins the initialization; the residual is thread reduction order. Both must be pinned, so run_fortran_amica now sets seed (from its own seed argument, which it previously accepted and ignored) and max_threads 1 as overrides rather than reading them from params.

End-to-end through the harness: two reference runs are now bit-identical.

A trap this opened

native/validate_shim.sh calls patch_sources.py --pin-seed. With the source already patched, patch() sees its marker and returns early, so --pin-seed would have silently done nothing and the shim-vs-mpif90 comparison would have run non-deterministic builds. --pin-seed now edits the file after patching, and fails loudly if its anchor is missing.

A bug my own unit tests missed

The first cut wrote field_dim [30504] — Python list repr — and the Fortran parser aborted at read time. Every unit test passed because they all used hand-picked keys; files and field_dim are lists in the real sample_params.json. Caught only by running the harness.

There is now a test that feeds the actual sample_params.json through and asserts no value keeps list syntax, plus one for space-separated list rendering.

Compatibility

The legacy amica15mac remains the default binary and still runs: the Fortran parser has no case default, so it silently ignores the seed keyword. Verified.

What this unblocks

#228's remaining question was which of four gate designs to adopt given a non-reproducible reference. With the native engine the reference is now bit-reproducible, so a genuine parity gate is available — the choice becomes whether to make the native engine the harness default. That decision is not in this PR.

Native engine is now the harness default

run_fortran_amica resolves the native engine first and only falls back to the bundled fixture when it cannot, printing why and stating that the resulting comparison is uncontrolled.

Two caveats found by testing rather than assumed:

  • No native binary has been released yet, so today the default falls back unless PAMICA_NATIVE_BINARY points at a local build. The fallback is loud, not silent. Cutting a release with the binary attached is what makes this default real.
  • A binary predating PR Refuse degenerate fits in the AMICA wrapper (#50) #54 ignores the seed keyword in silence, because the parser has no case default. The run now checks the binary acknowledged the seed in its output and warns when it did not, so an uncontrolled comparison cannot be reported as a controlled one.

Verified with PAMICA_NATIVE_BINARY set: the default resolves to the native engine and two reference runs through the harness are bit-identical.

@neuromechanist
neuromechanist merged commit 17ae80d into main Aug 16, 2026
7 checks passed
@neuromechanist
neuromechanist deleted the 228-seedable-fortran branch August 16, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant