Skip to content

Conform PerturbedEquilibrium response & coupling matrices to coordinate-invariant field space (#233, first slice) - #277

Merged
github-actions[bot] merged 9 commits into
developfrom
feature/conform-powernorm-field-matrices
Jun 21, 2026
Merged

Conform PerturbedEquilibrium response & coupling matrices to coordinate-invariant field space (#233, first slice)#277
github-actions[bot] merged 9 commits into
developfrom
feature/conform-powernorm-field-matrices

Conversation

@logan-nc

Copy link
Copy Markdown
Collaborator

Summary

First slice of #233: form the PerturbedEquilibrium control-surface response matrices and resonant coupling matrices in the coordinate-invariant power-normalized field (b̃) space of Pharr (2026), extending the convention PR #225 introduced for the DCON energy eigenvalues. Closes the response matrices + coupling audit portion of #233 (field reconstruction, torque matrix, and the FFS displacement-space integration are explicitly deferred — see Follow-ons).

The matrices are replaced in place with their b̃-space forms; the flux-space forms remain fully recoverable from a newly exposed operator.

What changed

  • Shared transform — extracted compute_sqrtamat/compute_sqrt_jac_delpsi out of ForceFreeStates/PowerNorm.jl into a new Equilibrium/CoordinateInvariant.jl, plus control_surface_ptof = sqrtamat·√jarea. One source of truth for FFS and PE (FFS now delegates).
  • Response matrices conformed (ResponseMatrices.jl, Response.jl) — field_space_response_matrices applies P̃=ptof⁻¹·P·ptof (similarity), L̃/Λ̃=ptof⁻¹·(·)·ptof⁻† and ϱ̃=ptof†·ϱ·ptof (congruence). Internal physics (singular coupling, field reconstruction, scalar energies) stays in flux space, so all physical outputs are bit-identical.
  • Recovery operator exposedcontrol_surface_field_operator (ptof) written to HDF5 as response_matrices/powernorm_field_to_flux_operator, with recovery formulas (P_flux = ptof·P̃·ptof⁻¹, L_flux = ptof·L̃·ptof†, …) documented in the struct docstring and the Utils doc-tree.
  • Coupling matrices conformed + audited (SingularCoupling.jl) — C̃ = C·ptof on input; applied resonant scalars evaluated from flux-space C·Φ_xbefore conformance (bit-identical, no round-trip noise). LHS coordinate-invariance audit annotations added for resonant field, penetrated field, Δ′, and shielding current.
  • fluxfield rename (Pharr 2026) — tesla quantities consistently named "field" to remove units confusion: resonant_fluxresonant_field, C_resonant_fluxC_resonant_field, plot_resonant_fluxplot_resonant_field_amplitude (renamed to avoid colliding with the pre-existing plot_resonant_field summary). Genuine flux quantities (ψ, Φ_x, χ₁) untouched. Regression case (diiid_n1.toml) and the Fortran-comparison benchmark updated in lockstep.

Verification

  • Physics review (fortran-physics-reviewer): PASS — all four transform rules algebraically exact and mutually consistent (P̃=Λ̃·L̃⁻¹, ϱ̃=L̃⁻¹(Λ̃−L̃)L̃⁻¹); control_surface_ptof identical to PowerNorm's ptof; all LHS invariance annotations justified with no overclaim.
  • Unit testtest/runtests_coordinate_invariant.jl — 9/9 (recovery round-trip, transform consistency, energy-scalar invariance).
  • Regressionregress --cases diiid_n1 --refs develop,local28/28 tracked physical quantities 0.0e+00 (energies, Δ′, island half-widths, Chirikov, PE energies/torque, q-profile, singular surfaces). The 2 N/A rows are the intended resonant_fluxresonant_field key rename (develop predates the key); the local value is bit-identical to develop's old resonant_flux by construction.

Follow-ons (out of scope, tracked under #233)

🤖 Generated with Claude Code

logan-ncand others added 2 commits June 11, 2026 08:07
…rices to coordinate-invariant field space
Implements the first slice of issue #233: form the PerturbedEquilibrium
control-surface response matrices and resonant coupling matrices in the
coordinate-invariant power-normalized field (b-tilde) space of Pharr (2026),
extending the convention PR #225 introduced for the DCON energy eigenvalues.
- Extract the shared power-norm transform (compute_sqrtamat, compute_sqrt_jac_delpsi,
new control_surface_ptof = sqrtamat*sqrt(jarea)) from ForceFreeStates/PowerNorm.jl
into Equilibrium/CoordinateInvariant.jl as one source of truth for FFS and PE.
- Conform the control-surface matrices in place: P~=ptof^-1*P*ptof (similarity),
L~/Lambda~=ptof^-1*(.)*ptof^-dagger and rho~=ptof^dagger*rho*ptof (congruence).
Internal physics (singular coupling, field reconstruction, energies) stays in
flux space, so all physical quantities are bit-identical.
- Expose ptof in HDF5 (response_matrices/powernorm_field_to_flux_operator) with
documented recovery formulas so users can recover the flux-space matrices.
- Conform the resonant coupling matrices on input (C~=C*ptof); evaluate the applied
resonant scalars from flux-space C first so they carry no round-trip noise. Add
LHS coordinate-invariance audit annotations (resonant field, penetrated field,
Delta', shielding current).
- Rename tesla quantities flux->field per Pharr 2026 to remove units confusion:
resonant_flux->resonant_field, C_resonant_flux->C_resonant_field,
plot_resonant_flux->plot_resonant_field_amplitude. Genuine flux quantities
(psi, Phi_x, chi1) are untouched. Regression case and Fortran benchmark updated
in lockstep.
Verification: physics review PASS (all transform rules exact and consistent);
new unit test runtests_coordinate_invariant.jl 9/9 (recovery round-trip,
consistency, energy invariance); regression diiid_n1 develop vs local 28/28
quantities 0.0e+00 (the 2 N/A rows are the intended resonant_flux->resonant_field
key rename).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…arr 2026 weighting language
Pharr (2026) names the three normal-field Fourier decompositions by the area weight
applied to the FT integrand, all in tesla: bare b (normal field), b-bar (full-area
weighted), b-tilde (square-root-area weighted). "Power-normalized" was a Parseval
property, not Pharr's term, and is not intuitive. This pass conforms all code, h5 keys,
comments, docstrings, and regression labels to the weighting language.
- b-tilde "power-normalized field" -> "root-area-weighted field" everywhere
(CoordinateInvariant.jl, RootAreaWeighted.jl, PE Response/ResponseMatrices/Structs/Utils).
h5 key powernorm_field_to_flux_operator -> rootarea_field_to_flux_operator.
- Resonant/penetrated b-bar fields -> "area-weighted field": resonant_field ->
resonant_area_weighted_field (+ C_, penetrated_ variants) across struct fields, h5
keys, doc-tree, Analysis plot fn, Fortran benchmark, and the diiid_n1 regression case.
- psi_area -> b_psi_area_weighted: it is b^psi/<J|grad psi|> (the gpout_xbnormal normal
field, tesla), not the surface area — the old name was misleading.
- Kill "Power Normalized" in FFS: prose + regression labels (4 cases) -> "root-area-
weighted"; internal pn_* -> rootA_*; compute_power_norm_eigenvalues ->
compute_rootarea_eigenvalues; PowerNorm.jl -> RootAreaWeighted.jl. The h5 dataset/group
structure (eigenmode_energies, XiNorm) is term-neutral and unchanged.
- Add docs/src/field_conventions.md: authoritative b/b-bar/b-tilde <-> English <-> h5
table with an admonition prompting #267's conventions page to conform on merge.
Verification: package loads; runtests_coordinate_invariant 9/9; docs build clean
(field_conventions renders, no missing_docs/cross_reference errors); regression diiid_n1
develop vs local 28/28 quantities 0.0e+00 (pure rename — the 2 N/A rows are the
resonant_field -> resonant_area_weighted_field key rename, value bit-identical).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@logan-nc

Copy link
Copy Markdown
CollaboratorAuthor

Added: field-terminology standardization (commit 378cb4c8)

Per review discussion, this PR now also standardizes the field-amplitude vocabulary to Pharr (2026)'s weighting language. The paper names the three normal-field Fourier decompositions by the area weight on the FT integrand (all tesla); "power-normalized" was a Parseval property, not Pharr's term, so it's dropped:

symbolweightnameh5 token
b (bare)1normal fieldb_n
𝒥|∇ψ|area-weighted fieldarea
√(𝒥|∇ψ|)root-area-weighted fieldroot_area

Changes:

  • "power-normalized field" → "root-area-weighted field" (+ h5 key powernorm_field_to_flux_operatorrootarea_field_to_flux_operator).
  • resonant_field/penetrated_fieldresonant_area_weighted_field/penetrated_area_weighted_field (struct fields, h5 keys, Analysis, benchmark, regression case — all in lockstep).
  • psi_areab_psi_area_weighted (it's the gpout_xbnormal normal field in tesla, not the surface area — the old name misled).
  • "Power Normalized" killed in FFS: prose + regression labels (4 cases); internal pn_*rootA_*; compute_power_norm_eigenvaluescompute_rootarea_eigenvalues; PowerNorm.jlRootAreaWeighted.jl. The h5 dataset/group structure (eigenmode_energies, XiNorm) is term-neutral and unchanged.
  • New docs/src/field_conventions.md: authoritative terminology table with an admonition prompting DOCS - NEW FEATURE - Conventions Reference page: sign, coordinate, and field-amplitude/units conventions #267 to conform its conventions page on merge.

Verification: package loads; runtests_coordinate_invariant 9/9; docs build clean; regression diiid_n1 develop vs local 28/28 quantities 0.0e+00 (pure rename — the 2 N/A rows are the resonant_fieldresonant_area_weighted_field key rename, value bit-identical). No numeric behavior changed.

🤖 Generated with Claude Code

@logan-nc
logan-nc requested a review from eburschJune 12, 2026 01:24
@logan-nclogan-nc self-assigned this Jun 12, 2026
@logan-nclogan-nc added feature New capability refactor Behavior-preserving restructuring labels Jun 12, 2026
@logan-nc
logan-ncforce-pushed the feature/conform-powernorm-field-matrices branch from cdd05e0 to 378cb4cCompareJune 12, 2026 01:42
logan-ncand others added 2 commits June 11, 2026 22:14
… operator
`ptof` ("power-norm to flux") is stale after the power-normalized → root-area-weighted
terminology change. Verified from Pharr (2026)'s definitions that the operator
sqrtamat·√jarea maps the root-area-weighted field b̃ (tesla) to the poloidal flux Φ
(weber): Φ = √A·sqrtamat·b̃, and the inductances act on it as energy = Φ†L⁻¹Φ. So the
"field → flux" description is correct; rename the mnemonic accordingly:
- ptof → rootareafield_to_flux (incl. _block/_full/_inv locals)
- Equilibrium.control_surface_ptof → control_surface_rootareafield_to_flux (+ export)
- build_control_surface_ptof → build_control_surface_rootareafield_to_flux
- Introduce `R ≡ rootareafield_to_flux` shorthand in two dense math docstrings to keep
them under the 180-col margin.
- Sweep two leftover "power-norm" comments in the test files (reverted-commit fallout).
Operating the response/coupling layer directly in the three tesla fields (b, b̄, b̃) was
considered but deferred: it rescales the FFS energy eigenvalues by 1/A² and the stored
inductances by A² (moves tracked regression values, reopens the PR #225 energy
normalization) — a normalization change for its own issue, not a naming cleanup.
Pure rename — no behavior change. Package precompiles; runtests_coordinate_invariant
9/9; regression diiid_n1 develop vs local unchanged (28/28 OK; the 2 N/A are the earlier
resonant_field key rename, not this commit).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, drop flux from outputs
Eliminate poloidal flux Φ (weber) from the control-surface vocabulary and HDF5 output, operating
instead in the three Pharr (2026) field representations (all tesla): bare b, root-area-weighted b̃
(coordinate-invariant), area-weighted b̄. Flux is recovered, only if a user supplies/requests it, as
the scalar product Φ = A·b̄ — it is never stored.
- Equilibrium/CoordinateInvariant.jl: replace the flux operator control_surface_rootareafield_to_flux
with the field-translation operators rootarea_to_area_weight (Σ/√A, b̃→b̄) and
area_to_rootarea_weight (√A·Σ⁻¹, b̄→b̃).
- ForceFreeStates/RootAreaWeighted.jl: factor the surface area out of the energy operator. The
operator is now the pure √weight Σ and the energy is dW = c·b̃†·W_t·b̃ with the explicit scalar
c = jarea. Net-zero (verified): FFS et/ep/ev unchanged to within-ULP.
- PerturbedEquilibrium: store the b̃ response matrices unchanged (b̄ is not coordinate-invariant);
store the b̃→b̄ operator + scalar surface_area as recovery aids (replacing the flux operator).
Output forcing AND response control-surface spectra in b, b̃, b̄. SingularCoupling C-conform and
the scalar energies/torque are bit-identical (the latter kept in the well-conditioned flux basis).
- docs/field_conventions.md, tests, benchmark updated; benchmark reconstructs Φ = A·b̄ for the
Fortran Phi_x/Phi_tot comparison.
Regression diiid_n1 + solovev_n1 (develop vs local): all tracked quantities OK — PE energies/torque
0.0e+00, FFS energies within-ULP, every stability quantity identical. Only the (untracked) stored
operator and the new b/b̃/b̄ spectra change. runtests_coordinate_invariant: 16/16.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@logan-nc

Copy link
Copy Markdown
CollaboratorAuthor

@ebursch can consult @matt-pharr if needed. Really, this is mostly a no-op naming convention change to conform the code to @matt-pharr 's paper terminology

These building blocks implement the √area weighting of Pharr (2026),
"Coordinate-invariant flux-surface Fourier analysis in tokamaks". They are the
single source of truth for translating a flux-surface field component between the
three Pharr field representations (all in tesla), shared by the ForceFreeStates and

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using the term Pharr field could be confusing. Something like "between the three types of weighted fields (all in tesla) from Pharr 2026." would be more clear.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. You can use github's suggestion +/- button to just make these one-word changes in the future so the other reviewers can just click "accept".
image

@eburschebursch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@logan-nc I think this all looks good to me. Just made one comment on nomenclature. This is a huge add for user understanding and physics clarity.

Comment threadsrc/Equilibrium/CoordinateInvariant.jl Outdated
logan-ncand others added 4 commits June 21, 2026 14:54
…field-matrices
Bring 99 commits of develop (kinetic/ballooning restructure, conventions docs)
into the field-space conform branch. Conflict resolutions:
- docs/make.jl: keep develop's "Conventions Reference" nav entry; our
field_conventions.md content folded into docs/src/conventions.md after the
Root-Area Normalized Field section, and field_conventions.md removed.
- FieldReconstruction.jl: keep our b_psi_area_weighted rename (consistent across
the merged tree) with develop's no-space kwarg formatting.
- GeneralizedPerturbedEquilibrium.jl: keep our "root-area-weighted" terminology.
- runtests_fullruns.jl: combine both smoke-test comment rationales.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…esonant field
Add 2008-Park-Spectral_asymmetry_due_to_magnetic_coordinates.pdf to
docs/resources, cite it in the Resonant Field section of conventions.md to
motivate area-normalization of the resonant harmonic, and add the full entry
to the PerturbedEquilibrium citations list.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- conventions.md: "cooridante" -> "coordinate"
- citations.md: doubled "the the" -> "the"
- equilibrium.md: "Solev'ev" -> "Solovev"; "SolevevConfig" -> "SolovevConfig"
(matches the real struct name); "lorcfg" -> "larcfg" in a runnable example
- set_up.md: "for you installation" -> "for your installation"
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
github-actionsBot merged commit 8d74561 into developJun 21, 2026
4 checks passed
@github-actions
github-actionsBot deleted the feature/conform-powernorm-field-matrices branch June 21, 2026 21:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

featureNew capabilityrefactorBehavior-preserving restructuring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@logan-nc@ebursch