Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
2fdae82
SLAYER - NEW FEATURE - Add SLAYERParameters and dimensional builder (…
d-burg Apr 19, 2026
e0c7397
SLAYER - NEW FEATURE - Add Fitzpatrick Riccati inner-layer Δ solver (…
d-burg Apr 19, 2026
61d844a
Dispersion - NEW FEATURE - Add SurfaceCoupling residual building bloc…
d-burg Apr 19, 2026
9d089be
Dispersion - CLEANUP - Remove leftover Newton root-finder files
d-burg Apr 19, 2026
71d69c5
Dispersion - NEW FEATURE - Add MultiSurfaceCoupling determinant resid…
d-burg Apr 19, 2026
dba61ca
Dispersion - NEW FEATURE - Brute-force Q-plane scan + find_growth_rat…
d-burg Apr 19, 2026
6cd5a5c
Dispersion - NEW FEATURE - AMR scan + triangulation-based growth-rate…
d-burg Apr 19, 2026
7a0f507
SLAYER - NEW FEATURE - KineticProfiles + LayerInputs builders (PR 7/9)
d-burg Apr 19, 2026
b170b49
SLAYER - NEW FEATURE - SLAYERRunner orchestration module (PR 8/9)
d-burg Apr 19, 2026
43c3b1d
SLAYER - NEW FEATURE - main() integration + Solovev example + regress…
d-burg Apr 19, 2026
8bfe74f
REFACTOR - Group tearing-mode modules under src/Tearing/ umbrella
d-burg Apr 19, 2026
3f82b7d
GGJ - NEW FEATURE - Per-surface E, F, G, H, K, M coefficients + build…
d-burg Apr 19, 2026
3ddc6f5
ForceFreeStates - IMPROVEMENT - Tighten defaults + use_parallel for d…
d-burg Apr 21, 2026
0a91a46
Utilities - NEW FEATURE - NeoclassicalResistivity module + switchable…
d-burg Apr 21, 2026
ede6fe2
ForceFreeStates - NEW FEATURE - Expose full 2m×2m D' matrix via delta…
d-burg Apr 21, 2026
ded86fe
InnerLayer - BUG FIX - InnerLayerResponse{tearing,interchange} + fix …
d-burg Apr 21, 2026
6410cd7
Dispersion - NEW FEATURE - CoupledFull 2m×2m det(D'−D(γ)) dispersion …
d-burg Apr 21, 2026
2172518
Dispersion - NEW FEATURE - CoupledFull 2m×2m det(D'−D(γ)) dispersion …
d-burg Apr 22, 2026
f3fe71a
Dispersion - IMPROVEMENT - CoupledFortranMatch inner_kwargs pass-through
d-burg Apr 22, 2026
ec00846
SLAYER - BUG FIX - Align Julia coupled-SLAYER dispersion with Fortran
d-burg Apr 23, 2026
2573553
Dispersion / GGJ - PERFORMANCE - Parallel amr_scan + preallocated Gal…
d-burg Apr 23, 2026
dd39a49
GGJ - BUG FIX - Remove erroneous Δ_crit offset from 4m×4m Pletzer-Dew…
d-burg Apr 24, 2026
568e431
WIP - SLAYER + GGJ - BUG FIX - Equilibrium-derived per-surface dr_val…
d-burg Apr 25, 2026
cce935a
SLAYER - NEW FEATURE - Adaptive pole_threshold = |mean(Δ)| for find_g…
d-burg Apr 26, 2026
c45a634
ForceFreeStates - BUG FIX - Wire ctrl.parallel_threads into BVP path;…
d-burg Apr 28, 2026
48f433d
ForceFreeStates - PERFORMANCE - parallel_threads default 1 → 2 (≈20% …
d-burg Apr 28, 2026
c49d86b
SLAYER - PERFORMANCE - Convert Riccati ODE to scalar state (~30-40% f…
d-burg Apr 28, 2026
9ec12a0
SLAYER - DOCS - Document solver-AMR-topology coupling in Riccati docs…
d-burg Apr 28, 2026
adf27aa
SLAYER - PERFORMANCE - Pre-compute x-independent Riccati constants (~…
d-burg Apr 28, 2026
e7ce1c1
Dispersion - NEW FEATURE - amr_scan: snapshot_callback + max_cells_ac…
d-burg Apr 28, 2026
0fb5d75
Dispersion - NEW FEATURE - convergence_amr_resolution.jl: γ vs (nre0,…
d-burg Apr 28, 2026
5fd3a83
Dispersion - NEW FEATURE - multi_box_amr_scan: stripe scan with pre-s…
d-burg Apr 28, 2026
8bcd7f2
Dispersion - NEW FEATURE - find_growth_rates: spurious-root detection…
d-burg Apr 29, 2026
e97225c
Dispersion - IMPROVEMENT - find_growth_rates: polyline-walk concavity…
d-burg Apr 29, 2026
4c6fbe3
Dispersion - REFACTOR - find_growth_rates: drop :density flag, keep :…
d-burg Apr 29, 2026
33d791f
Dispersion - REFACTOR - find_growth_rates: remove dead angle_threshol…
d-burg Apr 29, 2026
af76269
Tearing.Runner - IMPROVEMENT - multi-box stripe scan + median-based p…
d-burg Apr 29, 2026
fda6597
EQUIL - BUG FIX - find_separatrix_crossing tolerates fixed-boundary e…
d-burg May 1, 2026
528062f
[WIP] Tearing.Dispersion - chooser_overrides warn-not-discard policy
d-burg May 9, 2026
9a42a61
Merge branch 'perf/riccati' into feature/tearing-growthrates
d-burg May 26, 2026
9609432
test - FIX - Unmask pre-existing SLAYER + multi-n fullruns failures p…
d-burg May 27, 2026
6f2a76e
Tearing - CLEANUP - Pre-merge audit: Coupled* consolidation, multi-n …
d-burg May 29, 2026
a12e25f
Tearing - NEW FEATURE - Add resistive layer thickness (del_s Riccati)…
d-burg Jun 8, 2026
4e6e088
Merge branch 'develop' into feature/tearing-growthrates
d-burg Jun 10, 2026
335f08e
Tearing - NEW FEATURE - Robust SLAYER γ extraction + pre-merge audit …
d-burg Jun 12, 2026
369911c
Tearing - IMPROVEMENT - Neoclassical resistivity default + derived Wi…
d-burg Jun 15, 2026
1e1c3e3
REGRESSION - BUG FIX - NaN-safe JSON caching and diff for no-root SLA…
d-burg Jun 15, 2026
6154cf5
Tearing - DOCS - Verify SLAYER inner-layer against Fortran slayer_gro…
d-burg Jun 15, 2026
f50b4bd
Tearing - CLEANUP - Remove Fortran citations from backend; cite paper…
d-burg Jun 17, 2026
3febe62
Merge branch 'develop' into feature/tearing-growthrates
d-burg Jun 17, 2026
65a9b3e
EXAMPLE - NEW FEATURE - DIIID kinetic profiles + NTV demo; ldp/mpsi=2…
d-burg Jun 21, 2026
0efb70b
REGRESSION - Track NTV torque in diiid_n1 case
d-burg Jun 21, 2026
cd3969a
TEST - Re-pin DIIID parallel-integration δW/Δ' for ldp grid
d-burg Jun 21, 2026
ce12c74
EXAMPLE - Drop verbose KineticForces section comment
d-burg Jun 21, 2026
8f0a7cc
EXAMPLE - Retarget DIIID equilibrium to Ip=1.15 MA; psihigh=0.995 (ca…
d-burg Jun 22, 2026
1803be9
TEST - Re-pin DIIID parallel-integration for Ip=1.15 equilibrium
d-burg Jun 22, 2026
ac6f2fa
EQUIL - NEW FEATURE - HDF5 kinetic-profile format with ASCII back-compat
d-burg Jun 24, 2026
5876b34
EQUIL - IMPROVEMENT - Update DIII-D-like example: edge-matched equili…
d-burg Jun 24, 2026
42a0796
KineticForces - CLEANUP - Remove per-evaluation debug prints from NTV…
d-burg Jun 24, 2026
641c2d1
TEST - CLEANUP - Reword parallel-integration et[1] comment
d-burg Jun 25, 2026
13e4d08
Tearing - BUG FIX - Address Copilot PR review (iota_e, Q_i doc, model…
d-burg Jun 25, 2026
edb4d26
Merge remote-tracking branch 'origin/feature/diiid-kinetic-profiles' …
d-burg Jun 25, 2026
bc5edf1
Tearing - REFACTOR - Unify SLAYER kinetic profiles on read_kinetic_fi…
d-burg Jun 25, 2026
98eadf4
Tearing - IMPROVEMENT - All-zero χ sentinel + pin SLAYER regression t…
d-burg Jun 25, 2026
c08901b
Tearing - CLEANUP - Drop Solovev SLAYER example + regression case
d-burg Jun 25, 2026
366fa53
Tearing - MERGE - Merge develop into feature/tearing-growthrates
d-burg Jun 26, 2026
905a819
Tearing - BUG FIX - Update SLAYER example config for develop's ForceF…
d-burg Jun 26, 2026
7e59499
Tearing - BUG FIX - Auto-derive D_R for SLAYER critical-Δ
d-burg Jun 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*.i
*.out
*.h5
# kinetic-profile inputs are tracked despite the blanket *.h5 (output) ignore
!examples/**/*kinetic*.h5
.vscode
*.DS_Store
*.pdf
Expand All @@ -26,3 +28,9 @@ pestotv
regression-harness/*.sqlite
regression-harness/*.sqlite-shm
regression-harness/*.sqlite-wal
scratch/
.claude/worktrees/
.claude/agent-memory/

# Local profiling scratch (one-off study scripts, not part of the package)
profiling/
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = "0.1.0"
[deps]
AdaptiveArrayPools = "4f381ef7-9af0-4cbe-99d4-cf36d7b0f233"
Contour = "d38c429a-6771-53c6-b99e-75d170b6e991"
DelaunayTriangulation = "927a84f5-c5f4-47a5-9785-b46e178433df"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Expand Down Expand Up @@ -36,6 +37,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[compat]
AdaptiveArrayPools = "0.3.5"
Contour = "0.6.3"
DelaunayTriangulation = "1.6.6"
DelimitedFiles = "1.9.1"
DiffEqCallbacks = "4.9.0"
Documenter = "1.14.1"
Expand Down
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ makedocs(;
"KineticForces" => "kinetic_forces.md",
"Forcing Terms" => "forcing_terms.md",
"Perturbed Equilibrium" => "perturbed_equilibrium.md",
"Inner Layer" => "inner_layer.md",
"Tearing" => "inner_layer.md",
"Analysis" => "analysis.md",
"Utilities" => "utilities.md"
],
Expand Down
29 changes: 24 additions & 5 deletions docs/src/inner_layer.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Inner Layer Module
# Tearing Module

The InnerLayer module provides abstract scaffolding for resistive inner-layer
models used in matched asymptotic expansions for resistive MHD stability
analysis. It currently includes the GGJ (Glasser–Greene–Johnson) shooting
method for computing the inner-layer response.
The `Tearing` module groups the resistive tearing-mode analysis stack:
`InnerLayer` (per-surface inner-layer matching data Δ(Q) for the GGJ and
SLAYER models), `Dispersion` (physics-agnostic complex-plane scan and
contour-intersection root extraction), and `Runner` (user-facing TOML
configuration, profile loading, and HDF5 output).

## InnerLayer

Expand All @@ -16,3 +17,21 @@ Modules = [GeneralizedPerturbedEquilibrium.InnerLayer]
```@autodocs
Modules = [GeneralizedPerturbedEquilibrium.InnerLayer.GGJ]
```

## SLAYER

```@autodocs
Modules = [GeneralizedPerturbedEquilibrium.InnerLayer.SLAYER]
```

## Dispersion

```@autodocs
Modules = [GeneralizedPerturbedEquilibrium.Dispersion]
```

## Runner

```@autodocs
Modules = [GeneralizedPerturbedEquilibrium.Runner]
```
21 changes: 21 additions & 0 deletions docs/src/kinetic_forces.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ Kinetic torque and energy calculations for perturbed equilibria.
Implements neoclassical toroidal viscosity (NTV) from the PENTRC formulation
([Logan & Park, 2013](citations.md); [Logan, 2015](citations.md)).

## Kinetic profile file formats

Kinetic profiles are read by `read_kinetic_file`, which dispatches on the file
extension:

- **HDF5 (`.h5`/`.hdf5`)** — the GPEC kinetic schema (recommended). Datasets
at the file root: required `psi` (normalized poloidal flux), `n_e`, `T_i`,
`T_e`, `omega_E` (and `n_i`, defaulting to `n_e` if omitted); optional
`omega_tor`, `chi_e` (perpendicular heat diffusivity ``\chi_\perp``), and
`chi_phi` (toroidal momentum diffusivity ``\chi_\phi``). Each dataset
carries a `units` attribute; the root carries `schema_version` and
`provenance`. Densities are m⁻³, temperatures eV, frequencies rad/s,
diffusivities m²/s. Write files with `write_kinetic_h5`.
- **ASCII (`.gpeckf`/`.kin`/`.dat`)** — legacy six-column whitespace table
`psi_n n_i n_e T_i[eV] T_e[eV] omega_E`, retained for backward
compatibility. Header rows are skipped.

The NTV calculation consumes `n_i, n_e, T_i, T_e, omega_E`; `chi_e`/`chi_phi`,
when present, are carried for the resistive-layer (SLAYER) analysis and ignored
here.

## Profile Scaling Knobs

Seven scaling factors are available on `KineticForcesControl` to modify kinetic
Expand Down
97 changes: 97 additions & 0 deletions examples/DIIID-like_SLAYER_example/gpec.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# DIII-D-like SLAYER tearing-mode growth-rate example.
# Reuses the equilibrium and H-mode kinetic profiles of the sibling
# DIIID-like_ideal_example (geqdsk referenced by relative path; not
# duplicated). Runs equilibrium + ForceFreeStates + SLAYER and skips
# PerturbedEquilibrium (ForceFreeStates.force_termination = true).

[Equilibrium]
eq_filename = "../DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode.geqdsk" # Path to equilibrium file
eq_type = "efit" # Type of the input 2D equilibrium file
jac_type = "hamada" # Coordinate system (hamada, pest, boozer, equal_arc)
power_bp = 0 # Poloidal field power exponent for Jacobian
power_b = 0 # Toroidal field power exponent for Jacobian
power_r = 0 # Major radius power exponent for Jacobian
grid_type = "log_asymptotic" # Radial grid packing type
psilow = 1e-4 # Lower limit of normalized flux coordinate
psihigh = 0.9995 # Upper limit of normalized flux coordinate
mpsi = 0 # Number of radial grid points (0 = auto-compute from psi_accuracy)
psi_accuracy = 0.001 # Target absolute error in q for auto-mpsi
mtheta = 256 # Number of poloidal grid points
newq0 = 0 # Override for on-axis safety factor (0 = use input value)
etol = 1e-10 # Error tolerance for equilibrium solver
force_termination = false # Terminate after equilibrium setup (skip stability calculations)

[Wall]
shape = "nowall" # Wall shape (nowall, conformal, elliptical, dee, mod_dee, filepath)
a = 0.2415 # Distance from plasma (conformal) or shape parameter
aw = 0.05 # Half-thickness parameter for Dee-shaped walls
bw = 1.5 # Elongation parameter for wall shapes
cw = 0 # Offset of wall center from major radius
dw = 0.5 # Triangularity parameter for wall shapes
tw = 0.05 # Sharpness of wall corners (try 0.05 as initial value)
equal_arc_wall = true # Equal arc length distribution of nodes on wall

[ForceFreeStates]
force_termination = true # Run FFS + SLAYER, skip PerturbedEquilibrium
local_stability_flag = true # Perform local stability analysis (Mercier and ballooning) across the ψ profile
mat_flag = true # Construct coefficient matrices for diagnostic purposes
ode_flag = true # Integrate ODEs for stability of the internal long-wavelength mode (must be true for GPEC)
vac_flag = true # Compute plasma, vacuum, and total energies for free-boundary modes

psiedge = 0.99 # Edge dW scan band: dW(ψ) computed for ψ ∈ [psiedge, psilim], integration truncated at peak
qlow = 1.02 # Integration initiated at q determined by min(q0, qlow)...
qhigh = 1e3 # Integration terminated at q limit determined by min(qa, qhigh)...
sing_start = 0 # Start integration at the sing_start'th rational from the axis (psilow)

nn_low = 1 # Smallest toroidal mode number to include
nn_high = 1 # Largest toroidal mode number to include
delta_mlow = 8 # Expands lower bound of Fourier harmonics
delta_mhigh = 8 # Expands upper bound of Fourier harmonics
mthvac = 512 # Number of points used in splines over poloidal angle at the plasma-vacuum interface
thmax0 = 1 # Linear multiplier on the automatic choice of theta integration bounds

kinetic_source = "fixed" # Kinetic matrix source: "fixed" test matrices, or "calculated" from the kinetic NTV model
kinetic_factor = 0.0 # Scaling of kinetic matrices (0 = ideal path; >0 enables kinetic mode)
eulerlagrange_tolerance = 1e-10# Relative tolerance for ODE integration of Euler-Lagrange equations
save_interval = 3 # Save every Nth ODE step (1=all, 10=every 10th). Always saves near rational surfaces.
singfac_min = 1e-4 # Fractional distance from rational q at which ideal jump enforced
ucrit = 1e4 # Maximum fraction of solutions allowed before re-normalized

# Δ' BVP + parallel integration (see ForceFreeStatesControl docstring for details)
use_parallel = true # Run parallel FM-propagator BVP path (unlocks singular/delta_prime_matrix)
parallel_threads = 1 # serial/bit-deterministic BVP — keeps the regression Δ' (and hence γ) reproducible
populate_dense_xi = false # No PerturbedEquilibrium here; the dense EL pass has no consumer (auto-disabled under force_termination anyway). SLAYER needs only delta_prime_matrix from the parallel BVP.
truncate_at_dW_peak = false # Edge-dW scan stays diagnostic; integration domain set by qhigh / psihigh / dmlim
set_psilim_via_dmlim = true # TRUE for diverted geqdsks — q → ∞ at separatrix, so dmlim truncation avoids the δW kink instability at negligible domain cost
dmlim = 0.2 # Truncate integration at (last_rational_q + dmlim) / n

[SLAYER]
# SLAYER tearing-mode growth-rate analysis on the DIII-D-like H-mode equilibrium.
# Runs in the force_termination path (PE skipped). Kinetic profiles (incl. the
# χ⊥/χ_φ heat/momentum diffusivities) are read from the standardized HDF5
# kinetic file shared with the kinetic/NTV physics. Per-surface (uncoupled)
# analysis: the headline is the unstable 2/1; the validity gate drops surfaces
# with no real root (e.g. the 5/1, whose Δ' BVP yields a huge uncancellable Δ').
enabled = true
inner_model = "slayer_fitzpatrick"
scan_mode = "amr"
coupling_mode = "uncoupled"
dc_type = "none"
mu_i = 2.0
zeff = 1.0
chi_perp = 1.0 # fallback only; the kinetic file supplies χ⊥(ψ)
chi_tor = 1.0 # fallback only; the kinetic file supplies χ_φ(ψ)
pole_threshold_adaptive = true # SLAYER |Δ| spans many orders; adapt to 10·median(|Δ|)
filter_above_poles = true
filter_outside_re = true
polish_roots = true # refine each root to the true zero; enables the validity gate
store_scan = false # per-surface scans omitted from HDF5 (uncoupled has one per surface)
# Standardized kinetic-profile file (GPEC HDF5 kinetic schema), shared with the
# sibling ideal example; carries n_e, T_e, T_i, omega_E, chi_e (χ⊥), chi_phi (χ_φ).
profile_file = "../DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode_kinetic.h5"

[SLAYER.scan_grid]
Q_re_range = [-2.0, 2.0]
Q_im_range = [-0.5, 3.0]
nre = 41
nim = 31
Loading
Loading