Repository navigation
Description
Summary
The ideal crossing in both integrators is first order in singfac_min. Mapping the solution across the surface
through the Frobenius bases that are already computed removes that dependence: in a scratch prototype the edge
Riccati matrix and the free-boundary energy are flat in singfac_min to ~1e-9 and ~1e-7, and the existing
crossings converge linearly to the same values.
Current behavior
riccati_cross_ideal_singular_surf! (Riccati/Crossings.jl) and cross_ideal_singular_surf!
(EulerLagrange.jl) zero the resonant column, take a two-point trapezoidal step across the surface, and zero
the resonant row before inserting the small solution. The step and the row zeroing each leave an
O(singfac_min) error.
DIII-D-like n = 1 example, eulerlagrange_tolerance = 1e-10, free-boundary et[1]:
singfac_min |
Riccati (current) | Forward (current) | Riccati (prototype jump) |
|---|---|---|---|
| 1e-3 | 0.84554 + 3.3e-3i | 0.82231 | 0.79789523 + 8e-11i |
| 1e-4 | 0.80320 + 4.1e-4i | 0.80061 | 0.79789529 + 8e-11i |
| 1e-5 | 0.79847 + 4.6e-5i | 0.79818 | 0.79789529 − 1e-10i |
| 1e-6 | — | 0.79793 | — |
Edge S (Riccati, relative to the jump at 1e-6): current 1.3e-2 / 1.6e-3 / 1.9e-4 at 1e-3 / 1e-4 / 1e-5 with an
anti-Hermitian part of the same order; jump ≤ 6e-8 with anti-Hermitian part ~1e-10. The Solovev example behaves
the same way (6.1e-3 → 6.7e-5 against ≤ 1e-8).
Proposed change
At a crossing, with ua_L, ua_R from sing_get_ua:
ca = ua_L \ u, the coefficients in the left Frobenius basis (whatsing_get_careturns).- For each resonance, eliminate the big-solution coefficient from every column using the column where it is
largest, and move the surviving column out of the slot the small solution will take. - Zero the big and small coefficient rows.
u_R = ua_R · ca, then place the right small solution in the freed column. No resonant-row zeroing.
Both the elimination and the basis transfer are needed: elimination alone halves the error, and the transfer
without elimination is worse than the trapezoid.
Scope
- Riccati path (
_predict_across_singular_surface!,_capture_right_crossing_data!). - Forward path, recording the elimination and permutation for
transform_u!. - Multi-n shared surfaces, reversed shear (double crossing), Mercier-unstable (complex α).
- Regression cases: a
singfac_minscan ofet[1]ondiiid_n1andsolovev. - Revisit the
singfac_mindefaults (1e-4 for Riccati Δ′, 1e-6 for Forward decks feeding
PerturbedEquilibrium) once the crossing no longer sets them.
Not covered
- The Δ′ matrix is unchanged by the crossing (it comes from the propagator BVP) and still drifts with
singfac_min: first diagonal entry 9.089 at 1e-3, 9.241 at 1e-4. Separate issue. - Kinetic crossings (
cross_kinetic_singular_surf!) are untouched.
Impact
Results change at every current singfac_min by the size of the present defect (about 3e-5 in et[1] for
Forward at 1e-6, about 5e-3 for Riccati at 1e-4), so regression baselines move. Run time per solve is unchanged;
a larger singfac_min becomes usable (2.6 s at 1e-3 against 3.9 s at 1e-6 on the case above).
Evidence and caveats
Prototype: method overrides in a scratch script on v2.0.1, two equilibria, n = 1, Riccati path only for the
jump. The Forward numbers above are the unmodified code. Not yet tested: the Forward implementation, multi-n,
complex α, and PerturbedEquilibrium outputs.
Background: Schiff & Shnider, SIAM J. Numer. Anal. 36, 1392 (1999). Their Möbius-scheme result needs continuous
coefficients, so it does not remove the ideal crossing, but it motivates treating the crossing as a map on the
solution subspace.
Activity
jhalpern30 commentedon Nov 10, 2026
Related open work
Supersedes / fixes
singfac_min): this is its coefficient-space option. With it the jump no longer needs its own distance key. The first-order drift measured there (DIIID-like forward et₁ changing by 2.69e-3 → 3.0e-5 per 100× insingfac_min) is the same drift as in the table above; absolute et₁ values differ slightly between the two tables because the runs used different tolerances and vacuum resolution.Should land first
cross_ideal_singular_surf!. The Riccati half of this issue does not depend on it.OdeStatewith both ForceFreeStates - BUGFIX! - Trigger the Gaussian reduction on the conditioning of U₁ and factor U₁ in the plasma response matrix #520 and this.Should land after
EulerLagrange.jl/Riccati/Crossings.jlonly.Unblocked by this
Partly addressed
Not addressed
singfac_minis also the Δ′ matching distance. The Δ′ drift withsingfac_minneeds its own issue.Must keep passing
singfac_min = 1e-6in the Forward decks (#555) can be revisited once this lands.