PyroScan: how fields, eigenfunctions and time are reduced when loading a scan - #601
Closed
FelixWattsYork wants to merge 32 commits into
Closed
FelixWattsYork wants to merge 32 commits into
FelixWattsYork wants to merge 32 commits into
Conversation
…into feature/gftm
TGLF keys are stored lowercase by parse_tglf and uppercased on write, so
add_flags({"NBASIS_MAX": 6}) added a second key and the written file
contained NBASIS_MAX twice. Match flags to existing keys regardless of
case and store new keys in lowercase.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
Move the case-insensitive key matching into GKInput._add_flags_case_insensitive and use it for TGLF, CGYRO and NEO. New keys take the code's stored case: lowercase for TGLF, uppercase for CGYRO and NEO. Add NEO input tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
Use GKInput._add_flags_case_insensitive as TGLF does, so e.g.
add_flags({"NBASIS_MAX": 6}) overwrites the parsed nbasis_max instead
of writing NBASIS_MAX twice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
TGLF keys are stored lowercase by parse_tglf and uppercased on write, so
add_flags({"NBASIS_MAX": 6}) added a second key and the written file
contained NBASIS_MAX twice. Match flags to existing keys regardless of
case and store new keys in lowercase.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
Move the case-insensitive key matching into GKInput._add_flags_case_insensitive and use it for TGLF, CGYRO and NEO. New keys take the code's stored case: lowercase for TGLF, uppercase for CGYRO and NEO. Add NEO input tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
This reverts commit 2e27713.
This reverts commit 266a889.
This reverts commit 3cadb67.
add_flags({"NBASIS_MAX": 6}) overwrites the parsed nbasis_max instead of
adding a second key that is written as a duplicate NBASIS_MAX line. New
keys are stored in lowercase, as parse_gftm does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
Replace the per-code add_flags overrides and the _add_flags_case_insensitive helper with one GKInput.add_flags. Top-level keys match existing keys case-insensitively; new keys are converted with the class attribute flag_key_case (lowercase for TGLF, uppercase for CGYRO and NEO). dict values are merged into namelist groups as before. The GS2, GX, GKW, STELLA and GENE overrides only called super() and are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
Flag behaviour depends on the input format, not the code. Replace the single add_flags that dispatched on isinstance(value, dict) with one implementation per format: - GKInput.add_flags: grouped inputs (Fortran namelists, TOML tables). Raises TypeError if a value is not a dict of parameters. - GKInputFlat.add_flags: flat KEY = value inputs (TGLF, CGYRO, NEO). Matches keys case-insensitively, converts new keys with flag_key_case, and raises TypeError if a value is a dict. Both validate all flags before changing self.data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PwWRH3BAPwMdmNx4D3gEbV
FelixWattsYork
changed the base branch from
claude/default
to
feature/claude/pyroscan-ragged-grids
September 28, 2026 13:48
GFTM Implementation in Pyrokinetics
…pitilsation Case-insensitive add_flags, with one implementation per input format
…g a scan load_gk_output reduced phi, apar and bpar to ky[0] and the smallest |kx|, averaged nonlinear fields over time as complex values (a mean that cancels), always took linear growth rates at the last time, and set its time handling per regime. - One time_mode for linear and nonlinear runs alike: "average" (default, over [tolerance_time_range * t_max, t_max], tolerance_time_range 0.8), "last" or "trace". Adds VALID_TIME_MODES and the "trace" mode of reduce_time. - A time mean of a complex field is meaningless, so with "average", fields and eigenfunctions with a time axis are reduced to |field|**2 averaged in time, taken before any kx/ky sum, and stored as phi_squared, apar_squared, bpar_squared and eigenfunctions_squared. Outputs without a time axis keep their values and names. - Fields and eigenfunctions go through the same select_kx_ky_time call and keep kx and ky unless summed with sum_kx / sum_ky (both default False; sum_ky also applies to fluxes). - SaturationRules uses eigenfunctions_squared when present, otherwise |eigenfunctions|**2 at the final time, and selects the smallest |kx| itself. Combines fix/pyroscan-fields-sum-ky-kx and feature/pyroscan-linear-time-average-clean, with eigenfunctions made consistent with the fields. Tests use the STELLA and GX linear outputs, which carry apar and bpar, and port test_pyroscan_nonlinear_field_spectrum. Rebuilt from main without the ragged-grid stacking of #600, which is a separate change. Co-Authored-By: FelixWattsYork <hmq514@york.ac.uk> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015uAPcpjjmFiayk58HuLCXu
FelixWattsYork
force-pushed
the
feature/claude/pyroscan-field-dims
branch
from
September 29, 2026 08:04
23a180a to
754e65a
Compare
Collaborator
Author
|
Closing in favour of #599, which is open from the same branch against
Generated by Claude Code |
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.
Problem
PyroScan.load_gk_outputreduced its outputs in ways the user could not change:phi,aparandbparwere cut toky[0]and the smallest|kx|. For a nonlinear run that is theky=0,kx=0mode.growth_rateandmode_frequencyalways took the last time point.Change
One time setting, for linear and nonlinear runs alike. The output already says which regime it is, so the user isn't asked to state it again.
time_modeapplies to every output:"average"(default): the mean over[tolerance_time_range * t_max, t_max], withtolerance_time_rangedefaulting to 0.8."last": the final time point."trace": the full time series.Fields and eigenfunctions under
"average". A time mean of a complex field is meaningless: linear fields are normalised to their final amplitude, and nonlinear Fourier coefficients keep changing phase. So for fields and eigenfunctions that have a time axis,"average"averages|field|**2instead. It is taken before anykx/kysum, so a summed result is a sum of squared amplitudes. The result is stored asphi_squared,apar_squared,bpar_squaredandeigenfunctions_squared, with squared units, never under the field names. Outputs without a time axis, such as TGLF fields, keep their values and names.kxandky. Fields and eigenfunctions go through one shared code path (select_kx_ky_time) and keepkxandkyunlesssum_kx/sum_kyare set. Both default toFalse, andsum_kyalso applies to fluxes.SaturationRulesuseseigenfunctions_squaredwhen present, and otherwise|eigenfunctions|**2at the final time. It selects the smallest|kx|itself.This combines the designs of
fix/pyroscan-fields-sum-ky-kxandfeature/pyroscan-linear-time-average-clean, and includes the author's follow-up changes.Behaviour changes for existing users
growth_rate,mode_frequencyand fluxes are averaged over the window rather than taken at the last time.*_squared, averaged in time. Usetime_mode="trace"or"last"to get the complex fields.kx. Fields, eigenfunctions and fluxes keepkyby default.Independence from #600
This PR is separate from #600 (stacking runs whose grids differ) and is based on
main. One limitation without #600:time_mode="trace"on a scan whose runs have different time grids, e.g. theCGYRO_linear_scanfixture, cannot be stacked. The default"average"removes the time axis, so it is unaffected.Tests
In
tests/test_pyroscan.py:apar/bparare tested on the STELLA and GX linear outputs (GX has more than oneky), withsum_ky/sum_kxand eigenfunctions checked against the fields.test_pyroscan_nonlinear_field_spectrumis ported fromfix/pyroscan-fields-sum-ky-kx.time_modeis tested with each value, on linear and nonlinear runs, including the*_squarednames and units.The scan tests pass locally on
mainalone (27).Supersedes
fix/pyroscan-fields-sum-ky-kxfeature/pyroscan-linear-time-average-clean🤖 Generated with Claude Code
https://claude.ai/code/session_015uAPcpjjmFiayk58HuLCXu