chartmap: type-bound invert_cart (Cartesian inverse) on fortnum solvers#340
Merged
Conversation
Add a type-bound cs%invert_cart(x, u_guess, u, geom_status) to the chartmap coordinate system: the warm single-point Cartesian inverse the full-orbit pusher needs, ported onto fortnum's multiroot_hybrid. - Interior solve: multiroot_hybrid in the pseudo-Cartesian chart w=(X,Y,phi) with the analytic Jacobian built from covariant_basis (no finite differences). The (X,Y) chart is regular through the magnetic axis where the polar Jacobian is singular. - Near-edge solve: a bracketed 1-D radial solve (multiroot_hybrid at n=1) along the seeded ray with the bracket [rho_lo, 1] enforced in the callback, so the radius cannot overshoot past 1; a marker leaving the plasma stalls cleanly on the clamped edge. - Cold multi-seed fallback reuses chartmap_invert_cart for seam-stale guesses. The orchestrator keeps the lowest-residual root across all paths. - Both callbacks reject rho>1 trials (large outward residual) so the line search cannot accept a clamped-edge point. Move the map-specific helpers into the chart: pseudocart_basis (polar->(X,Y) chain rule), w_to_u (X/Y axis regularization), radial_scale (|dx/drho|). geom_status is GEOMETRIC ONLY (CHARTMAP_LOCATED / CLAMPED_EDGE / OUTSIDE / NO_ROOT) and never encodes a confinement loss; any loss policy stays with the caller. Link fortnum into the neo target. Add a behavioral unit test that writes a self-contained reactor-scale Boozer chartmap (no map2disc dependency) and checks the round-trip recovers interior u to tolerance (interior, seam, near-axis, axis) and that near-edge and just-outside targets report the correct geometric status.
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.
What
Add a type-bound
cs%invert_cart(x, u_guess, u, geom_status)to the chartmapcoordinate system: the warm single-point Cartesian inverse the full-orbit
pusher needs, ported onto fortnum's released solvers, with the map geometry
owned by the chart and loss policy left to the caller.
multiroot_hybridin the pseudo-Cartesian chartw = (X, Y, phi) = (rho cos theta, rho sin theta, phi)with the analyticJacobian from
covariant_basis(no finite differences). The(X, Y)chartis regular through the magnetic axis where the polar Jacobian
dx/dtheta ~ rhomakesdet(Jc) -> 0.multiroot_hybridatn = 1) along the seeded(theta, phi)ray, with the bracket[rho_lo, 1]enforced in the callback so the radius cannot overshoot past 1. A marker
leaving the plasma stalls cleanly on the clamped edge instead of grinding.
the lowest-residual root across paths.
Map-specific geometry moves into the chart:
chartmap_pseudocart_basis(polar -> (X,Y) chain rule),
chartmap_w_to_u(X/Y axis regularization),chartmap_radial_scale(|dx/drho|).geom_statusis geometric only (CHARTMAP_LOCATED/CHARTMAP_CLAMPED_EDGE/
CHARTMAP_OUTSIDE/CHARTMAP_NO_ROOT) and never encodes a confinement loss;that decision stays with the caller (in SIMPLE, the guiding-centre test).
Why
The full-orbit Boris pusher in SIMPLE hand-rolled a damped Newton with a
backtracking line search to invert the chartmap every microstep. The inverse
is a property of the chart, so it belongs with the chart, and the generic
iteration belongs in fortnum. This PR is the libneo half: a chart-owned
inverse on fortnum solvers. The near-edge bracket removes the line-search
overshoot-into-the-clamp that made near-loss markers expensive. SIMPLE adopts
this in a separate change and keeps its loss policy unchanged.
Verification
fo check: build and tests pass. Fullfopipeline: Static OK (43 modules),Build OK, Lint OK.
New behavioral test
test_chartmap_invert_cart(ctest #48) passes all sixchecks: interior roundtrip LOCATED; seam roundtrip with stale phi LOCATED;
near-axis rho recovered via X/Y healing; axis point handled; last-surface point
CLAMPED_EDGE; past-edge target OUTSIDE with rho clamped to 1.
Pre-existing failures, not introduced here: 11 ctest cases
(
setup_chartmap_volume,setup_vmec_chartmap_pythonand the fixture-gatedtests that consume their output) fail because the system Python the test runner
uses lacks the
map2discmodule (installed only in the project.venv), so thechartmap/vmec fixtures are never generated. Confirmed identical on pristine
HEAD before any edit; none touch the
invert_cartcode path. Pointing therunner at the project
.venvis tracked as a follow-up.Follow-ups (not in this PR)
invert_cart_warmas a thin loss-policy shell overcs%invert_cart(mapgeom_status -> FO_OK/FO_LOCATE_FAILviaaccept_or_fail, keepfo_to_gc's guiding-centre loss test, the #427contract), then delete the duplicated SIMPLE-side inversion routines. Gate on
the FO golden-record / W7-X confined-fraction benchmark.
res_norm/radial_scalefromcs%invert_cartso thecaller classifies without re-evaluating the map.
.venvso the 11fixture-gated chartmap tests run.