Skip to content

InnerLayer.SLAYER - FEATURE! - Add perpendicular Prandtl number options and an ion heat diffusivity profile - #501

Open
ebursch wants to merge 8 commits into
developfrom
feature/slayer-pperp-models
Open

ebursch wants to merge 8 commits into
developfrom
feature/slayer-pperp-models

Conversation

@ebursch

@ebursch ebursch commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Release note

  • Audience: users
  • Numerical impact: none at the default P_perp_model = "chi_perp_e" (harness @ d5937d0)
  • Migration: rename chi_perp to chi_perp_e in [SLAYER] of gpec.toml (and the chi_perp keyword of build_slayer_inputs / slayer_parameters).

SLAYER can now build the perpendicular Prandtl number P_⊥ in several ways, selected with the new [SLAYER] P_perp_model option. The kinetic HDF5 schema gains an optional chi_i (ion perpendicular heat diffusivity) profile, and the DIII-D-like example kinetic file now carries one.

P_perp_model P_⊥ Reference
chi_perp_e (default, unchanged behaviour) τ_R χ⊥,e / r_s² —
chi_perp_i τ_R χ⊥,i / r_s² —
P_phi P_⊥ = P_φ Fitzpatrick, Phys. Plasmas 30, 092512 (2023), Eq. 143
D_perp τ_R D⊥ / r_s², with D⊥ built from c_β, η, χ⊥,e, χ⊥,i and the n, T gradients Fitzpatrick, Phys. Plasmas 29, 032507 (2022), Eq. 16
c_beta P_⊥ = c_β² (the χ⊥ → 0 limit of D_perp; a floor on P_⊥) J.-K. Park, Phys. Plasmas 29, 072506 (2022), Eq. 10 with the thermal-conduction term K dropped
tau_E P_⊥ = P_φ = τ_R/τ_E (needs tau_E [s]) Fitzpatrick, Phys. Plasmas 30, 092512 (2023), Eq. 131

chi_perp_e still sets the critical-Δ dc_tmp in every mode.

This PR also corrects the Park citation in the SLAYER file headers (SLAYER.jl, Riccati.jl, LayerThickness.jl, LayerParameters.jl). They cited "Park et al., Phys. Plasmas 29, 122505 (2022)", which does not exist; the paper is J.-K. Park, Phys. Plasmas 29, 072506 (2022), doi:10.1063/5.0093079, as docs/src/citations.md already lists.

Regression report

regress --cases diiid_slayer_n1,diiid_n1 --refs 0e68a0553,d5937d04e --force on feynman (SLURM, develop vs head after the develop merge, both fresh, manifest pinned).

Regression Report: diiid_slayer_n1
=========================================================================
Ref 1: 0e68a0553  @ 0e68a0553 (2026-10-05)
       env: julia 1.11.7, x86_64-linux-gnu, manifest f1e0eb38 (pinned), 112 threads/8 BLAS
Ref 2: d5937d04e  @ d5937d04e (2026-10-05)
       env: julia 1.11.7, x86_64-linux-gnu, manifest f1e0eb38 (pinned), 112 threads/8 BLAS
-------------------------------------------------------------------------
Quantity                            0e68a0553  d5937d04e  Diff     Status
-------------------------------------------------------------------------
SLAYER surface indices              [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER poloidal m                   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER toroidal n                   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER minor radius rs              [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER r-based shear                [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Lundquist S                  [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER D_norm                       [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER P_perp                       [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER tauk                         [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER iota_e                       [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Q_e                          [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Q_i                          [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Q_root [2/1,3/1,4/1]         [3 elem]   [3 elem]   5.2e-10  OK    
SLAYER ω_Hz [2/1,3/1,4/1]           [3 elem]   [3 elem]   2.7e-07  OK    
SLAYER γ_Hz [2/1,3/1,4/1]           [3 elem]   [3 elem]   1.3e-05  OK    
SLAYER no_root flags [2/1,3/1,4/1]  [3 elem]   [3 elem]   0.0e+00  OK    
SLAYER enabled flag                 1          1          0.0e+00  OK    
Runtime (s)                         268.8s     269.7s              --    
=========================================================================
Summary: 17 unchanged


================================================================
Case: diiid_n1 — DIII-D-like equilibrium, n=1, ideal + perturbed equilibrium
================================================================

Regression Report: diiid_n1
=================================================================================================
Ref 1: 0e68a0553  @ 0e68a0553 (2026-10-05)
       env: julia 1.11.7, x86_64-linux-gnu, manifest f1e0eb38 (pinned), 112 threads/8 BLAS
Ref 2: d5937d04e  @ d5937d04e (2026-10-05)
       env: julia 1.11.7, x86_64-linux-gnu, manifest f1e0eb38 (pinned), 112 threads/8 BLAS
-------------------------------------------------------------------------------------------------
Quantity                                      0e68a0553        d5937d04e        Diff       Status
-------------------------------------------------------------------------------------------------
total energy Re(et[1])                        8.012318e-01     8.012318e-01     0.0e+00    OK    
total energy Im(et[1])                        4.142530e-05     4.142530e-05     0.0e+00    OK    
plasma energy Re(ep[1])                       -1.348486e+00    -1.348486e+00    0.0e+00    OK    
vacuum energy Re(ev[1])                       2.149718e+00     2.149718e+00     0.0e+00    OK    
vacuum matrix min eigenvalue                  1.873976e-01     1.873976e-01     0.0e+00    OK    
plasma energy (all)                           [35 elem]        [35 elem]        0.0e+00    OK    
vacuum energy (all)                           [35 elem]        [35 elem]        0.0e+00    OK    
total energy (all)                            [35 elem]        [35 elem]        0.0e+00    OK    
ODE steps (saved)                             1429             1429             0.0e+00    OK    
ODE steps (total)                             1424             1424             0.0e+00    OK    
q0                                            1.204212e+00     1.204212e+00     0.0e+00    OK    
q95                                           4.781723e+00     4.781723e+00     0.0e+00    OK    
beta_t                                        1.327024e-02     1.327024e-02     0.0e+00    OK    
beta_n                                        1.372511e+00     1.372511e+00     0.0e+00    OK    
internal inductance li1                       8.842392e-01     8.842392e-01     0.0e+00    OK    
internal inductance li2                       7.080847e-01     7.080847e-01     0.0e+00    OK    
internal inductance li3                       7.304433e-01     7.304433e-01     0.0e+00    OK    
poloidal beta betap1                          6.680744e-01     6.680744e-01     0.0e+00    OK    
poloidal beta betap2                          5.349834e-01     5.349834e-01     0.0e+00    OK    
poloidal beta betap3                          5.518761e-01     5.518761e-01     0.0e+00    OK    
# singular surfaces                           5                5                0.0e+00    OK    
singular psi locations                        [5 elem]         [5 elem]         0.0e+00    OK    
singular q values                             [5 elem]         [5 elem]         0.0e+00    OK    
current beta betaj                            4.236478e-01     4.236478e-01     0.0e+00    OK    
plasma volume                                 1.829472e+01     1.829472e+01     0.0e+00    OK    
plasma current                                1.152130e+00     1.152130e+00     0.0e+00    OK    
mpert                                         35               35               0.0e+00    OK    
npert                                         1                1                0.0e+00    OK    
toroidal field bt0                            2.006573e+00     2.006573e+00     0.0e+00    OK    
wall field bwall                              3.880145e-01     3.880145e-01     0.0e+00    OK    
aspect ratio                                  2.845746e+00     2.845746e+00     0.0e+00    OK    
elongation kappa                              1.708350e+00     1.708350e+00     0.0e+00    OK    
q profile (checksum)                          0cd285cea88d...  0cd285cea88d...  identical  OK    
pressure profile (checksum)                   a1c48b266622...  a1c48b266622...  identical  OK    
Mercier D_I profile (checksum)                eeb06744e795...  eeb06744e795...  identical  OK    
resistive interchange D_R profile (checksum)  fa37296851f6...  fa37296851f6...  identical  OK    
ballooning Delta' profile (checksum)          6eb0ea075ccf...  6eb0ea075ccf...  identical  OK    
island half-widths                            [5 elem]         [5 elem]         0.0e+00    OK    
Chirikov parameter                            [5 elem]         [5 elem]         0.0e+00    OK    
||resonant area-weighted field||              5.189042e-04     5.189042e-04     0.0e+00    OK    
dominant-coupling singular values             [3 elem]         [3 elem]         0.0e+00    OK    
|forcing overlap with dominant mode|          1.415706e-04     1.415706e-04     0.0e+00    OK    
|delta_nominal| of coil set 1                 7.055344e-05     7.055344e-05     0.0e+00    OK    
||ddelta/d(shift)|| over coil sets            1.246238e-04     1.246238e-04     0.0e+00    OK    
||ddelta/d(tilt)|| over coil sets             4.180652e-07     4.180652e-07     0.0e+00    OK    
PE plasma energy                              3.422677e+00     3.422677e+00     0.0e+00    OK    
PE vacuum energy                              3.174510e+00     3.174510e+00     0.0e+00    OK    
PE surface energy                             5.826684e+00     5.826684e+00     0.0e+00    OK    
PE toroidal torque                            5.087465e-02     5.087465e-02     0.0e+00    OK    
NTV torque FGAR [N·m]                         5.296746e-01     5.296746e-01     0.0e+00    OK    
NTV kinetic energy dW FGAR [J]                7.924988e-02     7.924988e-02     0.0e+00    OK    
Runtime (s)                                   281.1s           285.0s                      --    
||forcing b~|| (root-area-weighted)           4.683328e-04     4.683328e-04     0.0e+00    OK    
resonant area-weighted field b^r              [5 elem]         [5 elem]         0.0e+00    OK    
=================================================================================================
Summary: 53 unchanged

Every quantity is unchanged in both cases: the default P_perp_model = "chi_perp_e" reproduces develop, and the new chi_i dataset is not read by the default model.

Notes for reviewers


🤖 Generated with Claude Code

ebursch and others added 5 commits October 5, 2026 10:28
… kinetic HDF5

Add an optional chi_i (ion perpendicular heat diffusivity) dataset to the
kinetic-profile reader and writer, alongside chi_e and chi_phi.

Ship chi_i in the DIII-D-like example kinetic file, built like its chi_e:
AOT CHI_I of DIII-D 147131 at 2300 ms, mapped rho_N -> psi_N with EFIT01
RHOVN, the spurious zero at psi_N = 1 dropped, Gaussian-smoothed with
sigma = 12 of 201 rho_N points (the width that best reproduces the
example chi_e from AOT CHI_E). Range 0.46-2.1 m^2/s.

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

New [SLAYER] P_perp_model selects how the perpendicular Prandtl number is built:
- chi_perp_e (default, unchanged numbers): tau_R*chi_perp_e/r_s^2
- chi_perp_i: tau_R*chi_perp_i/r_s^2 (kinetic-file chi_i, scalar fallback)
- P_phi: P_perp = P_tor (Fitzpatrick, Phys. Plasmas 30, 092512 (2023), Eq. 143)
- D_perp: tau_perp = r_s^2/D_perp (Fitzpatrick, Phys. Plasmas 29, 032507 (2022))
- c_beta: C^2 = P_perp with C = c_beta (Park et al., Phys. Plasmas 29, 122505 (2022))

Breaking: the [SLAYER] chi_perp key is renamed chi_perp_e. chi_perp_e still sets
the critical-Delta offset in every mode. Regression harness diiid_slayer_n1
develop vs local: 17 unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…= tau_R/tau_E)

A single [SLAYER] tau_E [s] for the whole plasma sets P_perp = P_tor = tau_R/tau_E
at every surface (Fitzpatrick, Phys. Plasmas 30, 092512 (2023), Eq. 131).
validate() requires a positive tau_E when this model is selected.

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

P_perp_model = D_perp now builds D_perp per surface from Eq. 16 of Fitzpatrick,
Phys. Plasmas 29, 032507 (2022), with eta_perp = eta_par:
  D_perp = c_beta^2 eta/mu0 + (2/3)(1 - c_beta^2)[eta_e tau_e/(1+eta_e) chi_perp_e
                                                 + eta_i tau_i/(1+eta_i) chi_perp_i]
using the n, T_e, T_i log-gradients at the surface (Eqs. 4-6, written flat-density
safe). The scalar D_perp input is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e DIII-D-like SLAYER example

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added changed-results Results move or an interface breaks - read before upgrading feature New capability labels Oct 5, 2026
@ebursch ebursch self-assigned this Oct 5, 2026
@ebursch

ebursch commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Effect of each P_perp_model on the DIII-D-like SLAYER example

Setup: examples/DIIID-like_SLAYER_example at 27d0744, run once per model with only P_perp_model changed. The run is uncoupled, uses AMR and is validity-gated. χ⊥,e, χ⊥,i and χ_φ come from the chi_e, chi_i and chi_phi profiles in TkMkr_D3Dlike_Hmode_kinetic.h5. For tau_E I used τ_E = 0.1 s, a typical DIII-D H-mode value, which is not derived from this equilibrium. All three surfaces found a root in every run.

P_perp_model P_⊥ (2/1, 3/1, 4/1) P_φ (2/1, 3/1, 4/1) γ [Hz] (2/1, 3/1, 4/1) Δγ vs default (2/1, 3/1, 4/1) ω [Hz] 2/1
chi_perp_e 50.3, 44, 35.7 34.7, 24.7, 19 192, -251, -1012 — -10527
chi_perp_i 29.9, 26.4, 12.5 34.7, 24.7, 19 213, -274, -1217 +11 %, -9 %, -20 % -10523
P_phi 34.7, 24.7, 19 34.7, 24.7, 19 206, -277, -1123 +8 %, -10 %, -11 % -10525
D_perp 16.4, 17.5, 10.9 34.7, 24.7, 19 242, -296, -1249 +26 %, -18 %, -23 % -10516
c_beta 0.0133, 0.0088, 0.00645 34.7, 24.7, 19 313, -588, -1669 +63 %, -134 %, -65 % -10133
tau_E 34.5, 30.8, 27.6 34.5, 30.8, 27.6 206, -264, -1034 +8 %, -5 %, -2 % -10525

The Δγ column is (γ − γ_default)/|γ_default|, so + means more unstable. For scale, the run-to-run AMR noise on γ is about 0.01 %.

Takeaways

  • Only c_beta changes the answer qualitatively. Its P_⊥ = c_β² ≈ 0.01, three to four orders of magnitude below every other model. The 2/1 drive rises about 60 %, the stable 3/1 and 4/1 roots damp 65–135 % harder, and ω on the 2/1 shifts about 4 %. Every other model shifts ω by less than 0.1 %.
  • The χ-based models move γ by roughly 10–25 %.
    • chi_perp_i uses the example's χ⊥,i, which is about 0.4–0.6 of χ⊥,e at these surfaces. That halves P_⊥ and moves γ by about 10 % at the 2/1 and 3/1 and 20 % at the 4/1.
    • D_perp gives the smallest P_⊥ of the transport-based models, so it moves γ the furthest, by 18–26 %.
    • Across these models, a lower P_⊥ makes the 2/1 more unstable and the 3/1 and 4/1 more stable.
  • P_phi and tau_E land close together. With τ_E = 0.1 s, τ_R/τ_E happens to be close to the χ_φ-based P_φ on the 2/1. tau_E also overrides P_φ, so its 3/1 and 4/1 sit nearer the default. γ scales with the chosen τ_E, so these numbers only illustrate the model.
  • chi_perp_e (the default) reproduces develop exactly; see the regression report in the PR description.

The unit tests (Pkg.test() at 27d0744 on feynman) pass.


🤖 Generated with Claude Code

@ebursch

ebursch commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator Author

Example kinetic-file χ profiles vs the DIII-D 147131 AOT source

chi profiles: example .h5 vs AOT

Each panel compares TkMkr_D3Dlike_Hmode_kinetic.h5 (red dashed) with the AOT profile it was built from (blue): DIII-D 147131 at 2300 ms, mapped ρ_N → ψ_N with EFIT01 RHOVN. The grey lines mark the 2/1, 3/1 and 4/1 surfaces used in the SLAYER example. The bottom-right panel overlays the three .h5 profiles on one axis.

Dataset Status Source
chi_e (χ⊥,e) existing, unchanged AOT CHI_E, smoothed
chi_phi (χ_φ) existing, unchanged AOT ANG_MOM_DIFF, smoothed
chi_i (χ⊥,i) added in this PR AOT CHI_I; spurious zero at ψ_N = 1 dropped; Gaussian-smoothed with σ = 12 of 201 ρ_N points

At the SLAYER surfaces (new chi_i):

Surface ψ_N chi_i (.h5) AOT CHI_I .h5 vs AOT chi_i / chi_e
2/1 0.518 1.13 1.06 +7 % 0.59
3/1 0.770 1.80 2.10 −15 % 0.60
4/1 0.893 1.15 0.82 +39 % 0.35

Notes

  • Smoothing width: σ = 12 is the width that best rebuilds the existing chi_e from AOT CHI_E, about 10 % RMS in log over the profile.
  • Edge treatment differs: the existing chi_e and chi_phi also smooth over the pedestal well, the edge spike in CHI_E and the negative ANG_MOM_DIFF beyond ψ_N ≈ 0.94, so they stay positive and smooth to the edge. The file doesn't record how those edge treatments were done. The new chi_i uses only the Gaussian filter, so it follows the AOT well near ψ_N ≈ 0.93 and the rise to about 2 m²/s at the edge more closely.
  • 4/1 surface: the 4/1 sits on the inner flank of that well, where the smoothing lifts chi_i 39 % above AOT. A narrower σ would track AOT more closely there, at the cost of keeping more of the AOT structure elsewhere.

🤖 Generated with Claude Code

ebursch and others added 3 commits October 5, 2026 13:14
… and describe c_beta as the no-transport limit of D_perp

The SLAYER file headers and the c_beta P_perp_model cited "Park et al.,
Phys. Plasmas 29, 122505 (2022)", which does not exist. The paper is
J.-K. Park, Phys. Plasmas 29, 072506 (2022), doi:10.1063/5.0093079, as
docs/src/citations.md already lists. Its Eq. 10 defines
C² = c_β² + (1 − c_β²)K; C = c_β drops the thermal-conduction K, which
makes P_perp = c_β² the χ⊥ → 0 limit of the D_perp model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ebursch
ebursch marked this pull request as ready for review October 5, 2026 20:11
@ebursch
ebursch requested a review from d-burg October 5, 2026 20:11
@ebursch

ebursch commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator Author

@logan-nc @d-burg This adds a variety of options for perpendicular diffusion inputs. It doesn't change the default yet, so selecting the chi_perp_e is the same as what currently exists. You can see in the comparison that the only really different one is the c_beta which is good news (and encouragement to have this increased fidelity vs the Fortran slayer implementation). I think that we should move to full D_perp as default since there is not a literature justification for chi_perp_e ~ D_perp and if people already need chi_phi and chi_perp_e inputs than its not too crazy to also have them input chi_perp_i. It's encouraging that the tau_E choice is right order of magnitude (using tau_E = chi_phi and P_perp = P_phi) so that is also a helpful, user friendly, and control friendly option. After this gets merged, then either @d-burg or I should make a PR changing the default to D_perp and removing the chi_perp_e and chi_perp_i options. Let me know if you have any questions on this. Thanks!

@logan-nc

logan-nc commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

At a high level, this looks good. I agree that if someone has chi_phi and chi_perp_e, they likely have chi_perp_i on hand. If they don't have things, or are lazy then letting them assert a "reasonable" tau_E for their device is a great way to get results quick.

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

changed-results Results move or an interface breaks - read before upgrading feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants