Skip to content

PerturbedEquilibrium - BUGFIX! - Reject a perturbed equilibrium solved with a wall - #620

Merged
logan-nc merged 6 commits into
developfrom
bugfix/pe-reject-wall
Nov 1, 2026
Merged

logan-nc merged 6 commits into
developfrom
bugfix/pe-reject-wall

Conversation

@matt-pharr

@matt-pharr matt-pharr commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #613

What this does

The plasma response P = Λ·L⁻¹ took Λ from the run's δW, with its wall, and the surface inductance L from free space, so a run with a wall silently mixed two vacuum models. Now:

  • plasma_response errors on a force-free-states solve with a wall;
  • parse_deck stops on a deck with both [PerturbedEquilibrium] and [Wall].

Both error messages give the fix: solve without a wall.

The no-wall equilibrium

The Solovev decks relied on a conformal wall, because their n = 1 kink is unstable without one, and they cannot be re-tuned. A scan over q₀ ∈ [1.9, 5] and κ ∈ [1.0, 1.6] found et[1] < 0 everywhere. Solovev's pressure is linear in ψ, so the edge current is finite and drives a peeling/external kink.

Perturbed equilibrium now runs on eq_type = "tj_analytic", with no wall: R₀ = 10, a = 1, B₀ = 1, q₀ = 1.6, q_a = 3.2, p₀ = 0.1. It is stable (et[1] = 0.435) and keeps the 2/1 and 3/1 surfaces. psihigh = 0.99 is pinned, because et[1] moves by +0.502 at 0.995. The 3/1 surface sits at ψ_N = 0.955, outside the 0.9 core window, so the tests that use that window account for it.

  • New: TJ_ideal_example, and tj_n1 for it in the harness.
  • Moved: Solovev_kinetic_{NTV,multiion,calculated}_example become TJ_kinetic_*, with kinetic.dat and forcing.dat rebuilt for the new equilibrium. Their harness cases are renamed to tj_kinetic_*.
  • Stability only: Solovev_ideal_example keeps its wall and drops PE. solovev_n1 is unchanged.
  • Tests: the PE tests run on two new fixtures, regression_tj_ideal_example and regression_tj_kinetic_calculated.

Two harness cases also needed fixing:

  • solovev_kinetic_nuzero reused a deck that moved. It now runs the nuzero test fixture, widened by overrides to the same band and ion mix, and reproduces the old deck's values exactly.
  • lar_ggj_tearing_n1 never produced a result, because its deck writes gpec_lar_ideal.h5. It now overrides the output name.

Release note

  • Audience: users
  • Numerical impact: the PE and kinetic examples move to a new equilibrium, so their values are new under tj_*; every case that kept its deck is unchanged (harness @ f388c79)
  • Migration: a perturbed equilibrium needs a solve without a wall. Remove [Wall] from any deck with [PerturbedEquilibrium], or pass wall=nothing to solve. Solovev_kinetic_*_example are now TJ_kinetic_*_example, and Solovev_ideal_example no longer runs PE.

A perturbed-equilibrium calculation no longer silently combines a with-wall plasma energy with a free-space surface inductance. A run with a wall is now an error.

Regression report

Run against abc12d8eb, the head of #602 at the time (#602 has since merged into develop, adding only a case-TOML change that this branch also carries), on feynman: all cases at e375075bf, then the two repaired cases at f388c7910. That last commit changes only case TOMLs.

27 cases
22 cases, 325 quantities   unchanged, 0 changed
 1 case                    gal_resistive_pe: all N/A on both refs, as its TOML expects
 4 cases                   new, no baseline at abc12d8eb

tj_n1                  et[1] 0.4350277   beta_n 0.4156626   q0 1.599966   q95 2.980037   2 surfaces
tj_kinetic_ntv         fcgl 5.446400e-04 J   et[1] 0.4350277
tj_kinetic_multiion    NTV total 8.956676e-04 N·m (D 4.759306e-04, T 4.134019e-04, e 6.335161e-06)
tj_kinetic_calculated  et[1] 0.4380341   Im et[1] -1.957846e-03   NTV fgar 2.036734e-03 N·m

🤖 Generated with Claude Code

https://claude.ai/code/session_014wKUyAaxKdTJ5ch1boMFE1

@matt-pharr matt-pharr self-assigned this Oct 31, 2026
@github-actions github-actions Bot added bugfix Something was wrong and now is not changed-results Results move or an interface breaks - read before upgrading labels Oct 31, 2026
@matt-pharr
matt-pharr added this pull request to stack #621 October 31, 2026 08:22
matt-pharr and others added 3 commits October 31, 2026 17:48
…d with a wall

The plasma response P = Λ·L⁻¹ took Λ from the run's δW, with its wall, and the surface inductance L
from free space, so a wall run silently mixed two vacuum models. plasma_response now errors on a
force-free-states solve with a wall, and parse_deck stops on a deck with both [PerturbedEquilibrium]
and [Wall].

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

The Solovev kink needs a wall at every q0 and elongation scanned, so it cannot run a perturbed
equilibrium once a wall is rejected. TJ_ideal_example and the three TJ_kinetic_* decks replace the
Solovev PE decks on a TJ-analytic equilibrium stable at n = 1 with no wall (et[1] = +0.435).
Solovev_ideal_example keeps its wall and drops its PE stage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ixtures

Every test that runs a perturbed equilibrium now starts from a coarse TJ-analytic fixture with no wall.
The harness tracks the moved decks as tj_n1 and tj_kinetic_*; solovev_n1 stays as stability only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@d-burg
d-burg force-pushed the bugfix/pe-reject-wall branch from de5d179 to e375075 Compare October 31, 2026 23:00
solovev_kinetic_nuzero reused a deck that moved to the TJ equilibrium, so it now
runs the nuzero fixture widened to the same band and ion mix. lar_ggj_tearing_n1
reused a deck that writes gpec_lar_ideal.h5, which the harness never read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@d-burg

d-burg commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

@matt-pharr I've pushed the Solovev-to-TJ move for #613 onto this PR, so that swap is taken. The perturbed equilibrium examples, fixtures and harness cases now run on a no-wall tj_analytic equilibrium, stable with et[1] = 0.435 and keeping the 2/1 and 3/1 surfaces. The body has the details.

Harness against abc12d8eb: 22 of 27 cases unchanged, 325 quantities, nothing moved. Four cases are new and gal_resistive_pe is N/A as expected. Tests: 58 of 59 files pass on feynman. runtests_equil.jl:305, the exact-equality check on the re-formed i-file, fails there, but it fails the same way without this work.

Three things touch #602:

  1. lar_ggj_tearing_n1 doesn't run on Repo - API! - Consolidate the v2 deck sections, driver and HDF5 writers #602. Its deck writes gpec_lar_ideal.h5, so the harness reports "gpec.h5 not produced" on every ref and GGJ γ still isn't tracked. Adding "Run.output_file" = "gpec.h5" to [overrides] fixes it, and it runs now. It's in f388c7910 here; you may want it on Repo - API! - Consolidate the v2 deck sections, driver and HDF5 writers #602 too.

  2. The Z_eff range check can reject valid data. _layer_mass_per_electron checks the spline at each surface, and a spline can undershoot its nodes. Measured on the 514-node DIII-D-like file:

    Z_eff profile Node range Spline minimum ψ rejected
    As shipped [1.756, 1.924] 1.75603 0%
    Smooth, edge-peaked [1, 2.5] 1.0 0%
    Pedestal tanh [1, 1.993] 1.0 0%
    Flat 1, ramp from ψ = 0.8 [1, 2] 0.99959 0.82%
    Flat 1, steep ramp from ψ = 0.95 [1, 3] 0.99631 0.96%

    So every node can be valid and a surface near the kink still stops the run, with an error saying no ion split exists. The shipped decks are safe. Suggested fix: check the node values once instead of the spline at each surface. That keeps [1, Z] and doesn't widen it.

  3. _layer_ion_mass rejects density-specified species. It sums s.fraction, which is NaN for a species given by density, so total > 0 fails and even a single such species stops with "needs main-ion species with positive fractions". kinetic_profile_splines accepts those decks. It also averages mixed charges with no check. Weighting by each species' density would cover both spellings.

Base automatically changed from refactor/v2-consolidation to develop November 1, 2026 22:46
@logan-nc

logan-nc commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Should this be moved from draft to ready?

logan-nc and others added 2 commits November 1, 2026 18:16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU
… parse time and in plasma_response

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU
@logan-nc
logan-nc requested a review from jhalpern30 November 1, 2026 23:25
@logan-nc logan-nc added this to the GPEC v2.0.0 milestone Nov 1, 2026
@logan-nc
logan-nc marked this pull request as ready for review November 1, 2026 23:25
@logan-nc

logan-nc commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

@matt-pharr @d-burg I took this over the line since #602 landed: merged develop (only conflict was the identical lar_ggj output-file line), added two tests for the new errors (plasma_response on a walled solve, and parse_deck with both [PerturbedEquilibrium] and [Wall]), dropped the stacked-on-#602 banner, and marked it ready with @jhalpern30 as reviewer. runtests_solve_api.jl (167) and runtests_deck_roundtrip.jl (113 + 12) pass. No src/ changes, so the harness stamp holds.

@logan-nc
logan-nc self-requested a review November 1, 2026 23:28
@logan-nc
logan-nc enabled stacked auto-merge November 1, 2026 23:29
@logan-nc
logan-nc added this pull request to the merge queue Nov 1, 2026
Merged via the queue into develop with commit 25380a8 Nov 1, 2026
21 checks passed
@logan-nc
logan-nc deleted the bugfix/pe-reject-wall branch November 1, 2026 23:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Something was wrong and now is not changed-results Results move or an interface breaks - read before upgrading

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PerturbedEquilibrium: a run with a wall mixes a with-wall Λ and a no-wall L

3 participants