Skip to content

Tearing.IslandFlattening - FEATURE - Flatten the pressure across islands of prescribed width and report the stored energy they remove - #677

Open
logan-nc wants to merge 3 commits into
developfrom
feature/island-flattening
Open

logan-nc wants to merge 3 commits into
developfrom
feature/island-flattening

Conversation

@logan-nc

@logan-nc logan-nc commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

Adds Tearing.IslandFlattening: static flattening of the equilibrium pressure across magnetic islands of prescribed width, with the stored energy and pressure the islands remove.

Part of #629 (critical field, vacuum islands and flattening): its third item, saturated-island pressure flattening. #665 carries the other two (the critical resonant field and the vacuum-island widths); #629 closes when both are in.

What it computes

For full island widths w (ψ_N) keyed by "m/n", every q = m/n surface of the equilibrium gets an island. Inside each island dp/dψ = 0; outside it the gradient is unchanged; overlapping islands are merged and flattened once; the pressure keeps its value at the last profile point and is integrated inward. This is the saturated-island profile of Fortran GPEC, evaluated in closed form for merged intervals [a_k, b_k]:

p_mod(ψ) = p(ψ) + Σ_{k: b_k > ψ} [p(b_k) − p(max(ψ, a_k))], ΔW = (3/2) ∫ (p − p_mod) dV,

so there is no grid dependence, and the per-surface Fortran estimate's double counting of overlaps does not arise. ΔW uses Gauss–Legendre on the profile knots and interval ends, exact for the piecewise-cubic integrands.

Outputs, in Tearing/IslandFlattening/:

  • W, ΔW, ΔW/W and the on-axis pressure drop;
  • each island's surface and flattened interval (with a flag when it reaches past the profile grid);
  • the merged intervals with the pressure drop across each, which for an edge interval is the pedestal-top pressure change;
  • p and p_mod on the profile grid.

Given a bootstrap profile (jbs_B keyword), the result also gives the part the islands remove (j_bs ∝ p′ to leading order, so it vanishes on the intervals). The deck route for that waits for a bootstrap-current source on develop.

Use

[Tearing.IslandFlattening]
widths = { "2/1" = 0.05, "3/2" = 0.03 }

A [Tearing] holding only this sub-table runs no layer solve. In a script: island_flattening(ffs.equil; widths=Dict("2/1" => 0.05)). Docs: docs/src/inner_layer.md.

Also

Utilities.record_inputs! keeps recorded sub-tables a result does not state, so [Tearing.IslandFlattening] is recorded beside [Tearing] rather than replacing it. The rule and src/Utilities/Output.jl are identical to #665 (MRE with saturated-island roots). A test merge with #665 conflicts only where both add to the same lists (includes, exports, deck sections, main's return, docs). Each conflict resolves by keeping both sides, with one exception: in tearing_from_deck each branch strips its own sub-table before deciding whether a layer solve runs, and the merge strips both. On the merged tree the island-flattening, modified-Rutherford, result-struct, SLAYER-runner, deck round-trip, rerun and solve-API suites all pass.

Review package

The rule drawn out, plus four checks on the DIII-D-like example: the profile, the leading-order limit, convergence of the Fortran grid rule to the closed form, and overlap counted once. https://claude.ai/artifact/SDY8PUQKf6fa4FdQLQLhHQ

Tests

  • test/runtests_island_flattening.jl checks four things:
    • The Fortran trapezoid rule on a fine grid converges to the closed form.
    • Narrow islands: ΔW → 0 and ΔW ∝ w, with the leading-order coefficient (3/2)(−p′) w V(ψ_s).
    • Overlapping islands are flattened once, checked against an independent quadrature.
    • Edge and inner clipping, the bootstrap fraction (uniform and peaked profiles), bad input, and the HDF5 layout.
  • Deck and API parity, including replay from the recorded deck, in test/runtests_solve_api.jl.
  • New harness case diiid_n1_island_flattening, which puts 3/2, 2/1 and 3/1 islands on the DIII-D-like example.

Release note

  • Audience: users
  • Numerical impact: none on existing quantities. All 27 existing cases are unchanged. The new case diiid_n1_island_flattening has no develop baseline (develop rejects the section): W = 5.83e5 J, ΔW/W = 8.72e-2. (harness @ 5d0483f vs develop f11d75a; the later f6aa34b changes only the input record and two comments) The full suite passes except runtests_equil.jl:312 (TokaMaker i-file), which fails identically on develop.
  • Migration: none. main returns one more field, island_flattening.

New [Tearing.IslandFlattening] section: static pressure flattening across islands of prescribed width, giving the stored energy and the pressure (pedestal-top included) the islands remove.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BgNxCBwLNHQmVq7iXMCTae

logan-nc and others added 2 commits November 13, 2026 22:14
…nds of prescribed width and report the stored energy they remove

New Tearing.IslandFlattening: dp/dpsi = 0 across islands of given full width at every
q = m/n surface, the union flattened once and the pressure anchored at the boundary, in
closed form. Reports W, delta_W, the pressure drop across each merged interval and on axis,
and, given a <j_bs.B> profile, the bootstrap fraction removed. Deck section
[Tearing.IslandFlattening] widths runs without a layer solve; output Tearing/IslandFlattening/.
record_inputs! keeps the rest of a section when a result states only its sub-tables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BgNxCBwLNHQmVq7iXMCTae
…ntions and keep an empty [Tearing] an error

Delta_W, Delta_W_over_W, Delta_p0, Intervals/Delta_p and Islands/rational_{m,n,psi}; the input
widths are no longer echoed into Islands/. A [Tearing] with nothing in it stops on inner_model
again; only one holding [Tearing.IslandFlattening] skips the layer solve. The bootstrap fraction
is stated as a fraction of the given profile's volume integral, and the docs say how to get the
toroidal current fraction. Tests for a peaked bootstrap profile and inner-edge clipping.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BgNxCBwLNHQmVq7iXMCTae
@logan-nc logan-nc self-assigned this Nov 14, 2026
@github-actions github-actions Bot added the feature New capability label Nov 14, 2026
… by the rule the MRE branch uses

record_inputs! now matches the modified Rutherford branch line for line: a result owns its section's scalars and the sub-tables it states, and recorded sub-tables it does not state are kept. This replaces the sub-table heuristic of the first commit, so the two branches merge in either order. Two comments reworded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BgNxCBwLNHQmVq7iXMCTae

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant