Skip to content

Correct normal-mode Green transformation - #93

Merged
kpentland merged 3 commits into
mainfrom
fix-normal-mode-greens
Aug 14, 2026
Merged

Correct normal-mode Green transformation#93
kpentland merged 3 commits into
mainfrom
fix-normal-mode-greens

Conversation

@nicamo

@nicamo nicamo commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Correct the transformation used to construct Green-function maps for active-coil and passive-structure normal modes.

The physical metal currents and normal-mode currents are related by

[
\vec{I}_m = P\vec{I}_d,
]

with the inverse transformation

[
\vec{I}_d = P^{-1}\vec{I}_m.
]

P^{-1} is therefore the correct transformation when recovering modal currents from physical currents.

The poloidal flux produced by physical metal currents is

[
\psi = \vec{I}_m^T G_m,
]

where (G_m) contains the Green maps for the physical metal elements. Substituting (\vec{I}_m=P\vec{I}_d) gives

[
\psi
= (P\vec{I}_d)^T G_m
= \vec{I}_d^T P^T G_m.
]

Consequently, the Green maps per unit normal-mode current must be

[
G_d = P^T G_m,
]

rather than (P^{-1}G_m).

This distinction matters because the passive-mode eigenvectors are independent but not generally orthogonal, so (P^T \neq P^{-1}).

Changes

  • Replace the use of Pmatrix_inverse in normal_modes_greens() with Pmatrix.T.
  • Evaluate the transformation as a flattened matrix multiplication, avoiding the previous large broadcasted intermediate array.
  • Document the current and Green-map transformations directly in normal_modes_greens().
  • Add focused tests demonstrating that:
    • (P^{-1}) correctly converts physical currents into modal currents.
    • (P^T G_m) produces exactly the same flux as reconstructing physical currents with (P) and applying the physical Green maps.
    • The test basis is explicitly non-orthogonal, so the test distinguishes (P^T) from (P^{-1}).
  • Correct the modal-flux plotting cells in Example 10.
  • Add the derivation above to Example 10.
  • Update the affected dynamics reference value following the corrected passive-mode selection.

Example corrections

Example 10 previously contained two separate plotting problems:

  1. The full-mode plot selected one Green map and multiplied every modal current by it.
  2. The reduced-mode plot reconstructed physical currents but then contracted them with a modal Green map.

The corrected example now illustrates both valid routes:

[
\psi = \vec{I}_d^T G_d
]

using modal currents and modal Green maps, and

[
\psi = \vec{I}_m^T G_m
]

after reconstructing the physical currents.

Behavioural impact

The circuit-current transformations in circuit_eq_metal.py were already correct and are unchanged.

The corrected Green maps are used when preparing initial finite-difference perturbations for passive-mode coupling calculations. Therefore, the correction can change which passive modes are selected for a fixed reduced-mode count. The corresponding dynamics regression reference has been updated while retaining its existing relative tolerance.

Active-coil Green maps are unaffected because the active-coil block of (P) is the identity.

Validation

  • Focused normal-mode and dynamics tests: 5 passed.

  • The remaining repository tests passed during the full-suite run, with 4 existing skips.

  • A MAST-U nonlinear-solver smoke test compared:

    • flux calculated directly from selected modal currents and (P^T G_m);
    • flux calculated after reconstructing physical currents with (P).

    Relative discrepancy:

    [
    5.4\times10^{-16}.
    ]

This is consistent with floating-point round-off.

@nicamo nicamo added the bug Something isn't working label Aug 4, 2026
@nicamo
nicamo changed the base branch from streamlining to main August 4, 2026 11:09
@kpentland kpentland self-assigned this Aug 11, 2026

@kpentland kpentland 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.

This all looks good - nice spot that P_inverse and P_transpose are not the same here - I recall this popping up before in our growth rate analysis

@nicamo nicamo added the ready-for-final-tests Pull request is ready to run final pre-merge tests label Aug 11, 2026
@kpentland kpentland added ready-for-final-tests Pull request is ready to run final pre-merge tests and removed ready-for-final-tests Pull request is ready to run final pre-merge tests labels Aug 14, 2026
@kpentland
kpentland merged commit 4a67e73 into main Aug 14, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ready-for-final-tests Pull request is ready to run final pre-merge tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants