Symptom
The reference holds the mixing-matrix update whenever iter >= share_start and mod(iter, share_iter) <= 5 (pamica/amica15.f90:1803, if (update_A .and. ((iter < share_start) .or. (mod(iter,share_iter) > 5)))), and it never checks share_comps. With the defaults (share_start = share_iter = 100, amica15_header.f90:76), every reference run of 100 or more iterations freezes A, and with it the lrate ramp, which lives inside the same branch, at iterations 100-105, 200-205 and so on. The bundled input.param (max_iter 2000, share_comps 0) therefore produced the amicaout fixture with 19 such windows. pamica's torch, NumPy and MLX backends freeze A only when share_comps is on, so default fits of 100 or more iterations diverge from the reference. Measured by epic #324 Phase 8 (PR #342): from a seeded state with share_comps=0, share_start=1 and doscaling=0, the binary's A after 2 iterations equals the seed exactly; with share_start=1000 it moves by 0.041. pamica.schedule.share_freeze's docstring, which says the path is dead in the reference, is wrong.
Fix
Apply the reference's freeze regardless of share_comps, with the reference's exact arithmetic (iter >= share_start and mod(iter, share_iter) <= 5, 1-based through pamica/schedule.py), in all three backends. Reconcile it with pamica's documented anchored-window A-freeze after a merge (docs/guides/amica-differences.md): keep that divergence only where it still differs from the reference, and say so. Gates: an always-on cross-backend test that A is unchanged on exactly the reference's frozen iterations with share_comps off; a gated native-binary oracle across a frozen window (for example share_start=3, share_iter=10, doscaling on and off) matching to round-off; and a re-measurement of the parity against the bundled amicaout fixture. Changelog: default fits of 100 or more iterations change trajectory toward the reference.
Part of epic #324; bundled with #339 (Phase 11), which also changes the order of the default iteration loop.
Symptom
The reference holds the mixing-matrix update whenever
iter >= share_startandmod(iter, share_iter) <= 5(pamica/amica15.f90:1803,if (update_A .and. ((iter < share_start) .or. (mod(iter,share_iter) > 5)))), and it never checksshare_comps. With the defaults (share_start = share_iter = 100, amica15_header.f90:76), every reference run of 100 or more iterations freezesA, and with it the lrate ramp, which lives inside the same branch, at iterations 100-105, 200-205 and so on. The bundledinput.param(max_iter 2000,share_comps 0) therefore produced theamicaoutfixture with 19 such windows. pamica's torch, NumPy and MLX backends freezeAonly whenshare_compsis on, so default fits of 100 or more iterations diverge from the reference. Measured by epic #324 Phase 8 (PR #342): from a seeded state withshare_comps=0,share_start=1anddoscaling=0, the binary'sAafter 2 iterations equals the seed exactly; withshare_start=1000it moves by 0.041.pamica.schedule.share_freeze's docstring, which says the path is dead in the reference, is wrong.Fix
Apply the reference's freeze regardless of
share_comps, with the reference's exact arithmetic (iter >= share_startandmod(iter, share_iter) <= 5, 1-based throughpamica/schedule.py), in all three backends. Reconcile it with pamica's documented anchored-window A-freeze after a merge (docs/guides/amica-differences.md): keep that divergence only where it still differs from the reference, and say so. Gates: an always-on cross-backend test thatAis unchanged on exactly the reference's frozen iterations withshare_compsoff; a gated native-binary oracle across a frozen window (for exampleshare_start=3,share_iter=10, doscaling on and off) matching to round-off; and a re-measurement of the parity against the bundledamicaoutfixture. Changelog: default fits of 100 or more iterations change trajectory toward the reference.Part of epic #324; bundled with #339 (Phase 11), which also changes the order of the default iteration loop.