Decouple integration microstep dtaumin from trace_time#433
Closed
krystophny wants to merge 1 commit into
Closed
Conversation
dtaumin was overwritten with dtau/ntau, tying the physical resolution to the total trace length: two runs differing only in trace_time integrated at slightly different microsteps (off-by-one in ntau), so confined-fraction curves of different length were not comparable and chaotic near-axis orbits flipped fate (an ~11% shift at 100 ms on the W7-X reactor case). Pin dtaumin = 2*pi*rbig/npoiper2 (resolution from npoiper2 only); derive the total microsteps from it and distribute them over the ntimstep output points by cumulative rounding in both the linear and log macrostep schedules. ntau is kept as a representative substep count for diagnostics. Add test_dtaumin_invariance: dtaumin is identical across a 10x trace_time change and equals the npoiper2 resolution target (was ~19% apart before).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Risk tier
Correctness contract
Intended behavior change
The integration microstep
dtauminno longer depends ontrace_time. It wasoverwritten with
dtau/ntau(dtau = trace_time*v0/(ntimstep-1)), so thephysical resolution was tied to the total trace length: two runs differing only
in
trace_timeintegrated at slightly different microsteps (an off-by-one inntau = ceiling(dtau/dtaumin)), and confined-fraction curves of differentlength were not comparable. On the W7-X reactor case this shifted the confined
fraction ~11% at 100 ms between a 0.1 s and a 1 s run with identical start.dat.
dtauminis now pinned to2*pi*rbig/npoiper2(resolution fromnpoiper2alone). The total microsteps are derived from it (
nint(tau/dtaumin)) anddistributed over the
ntimstepoutput points by cumulative rounding, in boththe linear and log macrostep schedules (the log branch already did this).
Behavior that must not change
Macrostep/output count (
ntimstep), log-grid 10:1 spacing, and the microstepresolution in the asymptotic regime (
dtau >> dtaumin, i.e. largentau):there the change is < 1 part in
ntau.Coordinate / unit conventions
Unchanged.
Numerical invariants
dtauminis a function of(rbig, npoiper2)only. Two runs differing only intrace_timeintegrate at identical resolution.Tests added
test_dtaumin_invariance-dtauminis identical across a 10xtrace_timechange and equals2*pi*rbig/npoiper2.Golden-record impact
Loss times shift. Measured against
run_main:max|dt| ~ 9.4e-5- thetotal-trace-time rounding on confined markers' final time. Negligible.
(
max|dt| ~ 2.5e2). Those configs request a coarsenpoiper2whose microstepthe old code silently refined for short traces; the orbits are chaotic, so
loss times decorrelate. The new resolution is exactly what
npoiper2asks for.All 12 golden records change for the corrected (now
trace_time-independent)behavior and need regeneration.
Failure modes considered
Degenerate short traces (
tau < nintv*dtaumin) are guarded byn_microsteps_total = max(nintv, nint(tau/dtaumin))so every macrostep keeps atleast one microstep.
init_symplis called with(dtaumin, dtaumin), so itsdtau/dtaumininteger check is unaffected.Manual validation
10/10 orbit/timestep/macrostep ctest pass (
test_macrostep_log_grid,orbit_netcdf_output,test_orbit_chartmap_comparison,test_orbit_refcoords_rk45, ...).Verification
Failing-before (old
dtaumin = dtau/ntau), TEST field npoiper2=256:Passing-after (pinned
dtaumin):