Skip to content

ErrorFields - FEATURE - Add a range-linearity check and per-coil scan controls to the tolerance Monte Carlo #474

Description

@logan-nc

Plan for the first ErrorFields follow-up after the current stack (#449 … #462, #473) merges into develop. Branch from develop then; do not stack it on the open PRs, since every item touches _resolve_terms in MonteCarlo.jl. Items come from the capability audit of the OMFIT error-field scripts against the Julia stack; each is small, and together they are one PR. Estimates are lines of source.

1. Range-linearity check (~40). The linear sensitivity model is asserted only locally: Sensitivity.jl stores a second-difference ratio at the finite-difference step, normalized by the set's largest first difference. Nothing checks that δ is linear out to the tolerance edge (and the cylinder tilt reach, and a coherent group's combined displacement), which is the premise every post-hoc sweep rests on; the reference scripts found S-curves at large tilts. Add linearity_check(ctx, coil_sets, tolerances; scales=(1, 2)) that evaluates applied_spectrum at ±scale·tol per degree of freedom and reports the relative error of the stored linear prediction, plus a plot sharing the loader of plot_linearity_residuals. Linearity in current needs no check (Biot–Savart). Open choice: check at each coil's own tolerance and twice it, or also at the largest scale of the tolerance scan; leaning to both ends of the scan.

2. Per-coil scan controls (~10). tolerance_scale multiplies every active coil and coil_subset sets the inactive ones to zero tolerance (_resolve_terms, active(t.name) || continue), so "scan class A while class B holds its own tolerance" is not expressible, and that is the reference's primary product plot. Let tolerance_scale accept a per-coil map (or add scale_subset: the coils the scale applies to, the rest at 1×), and make inactive coils hold their tolerance instead of dropping it. Open choice, to decide when implementing: key the map by coil name (no schema change) or add a class field to the tolerance TOML so it is keyed by class.

3. Coherent-group tilt_lever_arm_m (~5). A group tilt tolerance given in metres is converted through a member's major radius (group_tilt_deg, which now requires the members' radii to agree within 1 %). For a group representing a reference structure, the lever arm is a property of that structure, not of any member coil. Add an optional tilt_lever_arm_m key on [[ErrorFields.coherent_group]] that takes precedence over the member radius.

4. Per-coil current_factor (~10). A map applied to delta_nominal per coil in _resolve_terms, so the risk against the current in an uncorrectable coil (the reference's risk_vs_remc) is a user loop over run_monte_carlo. Also needs a keyword copy of ToleranceSet (or map_tolerances(f, ts), ~20) so sigmas and the unattributed budget can be varied programmatically; tolerance_scale deliberately does not touch them.

5. Monte Carlo validity tests (~30 of tests). None of the current tests would catch a systematic binning bias, which is exactly the bug the reference scripts had (risk moved with nsample while the batch spread said it should not). Add: Monte Carlo against the closed-form erfc risk for a Gaussian |δ| (synthetic table) × Gaussian threshold at several amplitudes where the true risk is well below a percent, agreement within batch spread; plock at nbins = 300 vs 3000 within spread; nsample convergence with the spread shrinking as √N. A shipped risk_convergence(...) diagnostic returning plock against nsample and nbins with spread is the same 30 lines.

Verification: the tolerance TOML, Monte Carlo and error-fields test files; the regression harness on diiid_n1 and diiid_error_field must be unchanged (defaults keep today's behaviour). Review package with the linearity and convergence figures on the DIII-D-like example.

Activity

  1. self-assigned this
    on Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions