Skip to content

Commit 2f385bd

Browse files
committed
Merge branch 'develop' into bugfix/kf-omega-d-major-radius
2 parents d061183 + 9a98f7c commit 2f385bd

2 files changed

Lines changed: 33 additions & 30 deletions

File tree

src/KineticForces/BounceAveraging.jl

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ end
147147

148148
"""
149149
compute_bounce_data(psi, n, l, q, bo, bmax, bmin, theta_bmax,
150-
tspl, B_extrap, mfac, chi1, ro, dbob_m_f, divx_m_f,
150+
tspl, B_vpar, mfac, chi1, ro, dbob_m_f, divx_m_f,
151151
divxfac, wdfac, mass, chrg, T_s, method;
152152
nlmda=128, ntheta=128,
153153
smat=nothing, tmat=nothing, xmat=nothing,
@@ -168,8 +168,8 @@ Ports Fortran torque.F90 lines 530-816 (GAR branch).
168168
- `bmax, bmin`: Max/min of B(θ) at this ψ
169169
- `theta_bmax`: θ location of Bmax (nodal knot; the passing-transit start)
170170
- `tspl`: Periodic poloidal interpolant: tspl(θ) → [B, dB/dψ, dB/dθ, J, dJ/dψ]
171-
- `B_extrap`: Endpoint-fit (non-periodic) cubic of B(θ) used for v_par and the
172-
bounce-point roots (the Fortran `vspl` equivalent)
171+
- `B_vpar`: Periodic cubic of B(θ) used for v_par and the bounce-point roots
172+
(the Fortran `vspl` equivalent)
173173
- `mfac`: Poloidal mode numbers [mlow:mhigh]
174174
- `chi1`: 2π·ψ₀ flux normalization
175175
- `ro`: Major radius [m]
@@ -190,7 +190,7 @@ function compute_bounce_data(
190190
psi::Float64, n::Int, l::Int, q::Float64,
191191
bo::Float64, bmax::Float64, bmin::Float64,
192192
theta_bmax::Float64,
193-
tspl, B_extrap, mfac::Vector{Int}, chi1::Float64, ro::Float64,
193+
tspl, B_vpar, mfac::Vector{Int}, chi1::Float64, ro::Float64,
194194
dbob_m_f::Vector{ComplexF64}, divx_m_f::Vector{ComplexF64},
195195
divxfac::Float64, wdfac::Float64,
196196
mass::Float64, chrg::Float64,
@@ -241,12 +241,12 @@ function compute_bounce_data(
241241

242242
# Find bounce points and build θ sub-grid
243243
_, _, tdt_pts, tdt_wts = _find_bounce_points_and_grid(
244-
lmda, bo, sigma, B_extrap, theta_bmax, psi, ntheta)
244+
lmda, bo, sigma, B_vpar, theta_bmax, psi, ntheta)
245245

246246
# Bounce integrals over θ (Fortran lines 674-735)
247247
wbbar, wdbar, dJdJ_val, wmats_lmda = _bounce_integrate(
248248
tdt_pts, tdt_wts, lmda, lnq, sigma, n, q, bo,
249-
tspl, B_extrap, chi1, ro, mfac, dbob_m_f, divx_m_f, divxfac, wdfac,
249+
tspl, B_vpar, chi1, ro, mfac, dbob_m_f, divx_m_f, divxfac, wdfac,
250250
do_matrices, mpert, smat, tmat, xmat, ymat, zmat, scr)
251251

252252
# Physical frequencies (Fortran lines 744-745)
@@ -409,12 +409,12 @@ end
409409

410410

411411
"""
412-
Parallel-velocity factor `v_par = 1 − (λ/bo)·B(θ)` from the endpoint-fit cubic of B
413-
(`B_extrap`, built where the surface interpolants are constructed), keeping v_par
412+
Parallel-velocity factor `v_par = 1 − (λ/bo)·B(θ)` from the periodic cubic of B
413+
(`B_vpar`, built where the surface interpolants are constructed), keeping v_par
414414
consistent with the bounce-point roots as in Fortran's `vspl`.
415415
"""
416-
@inline _vpar_from_extrap(B_extrap, lmda::Float64, bo::Float64, θ::Float64) =
417-
1.0 - (lmda / bo) * B_extrap(mod(θ, 1.0))
416+
@inline _vpar_from_spline(B_vpar, lmda::Float64, bo::Float64, θ::Float64) =
417+
1.0 - (lmda / bo) * B_vpar(mod(θ, 1.0))
418418

419419

420420
"""
@@ -423,14 +423,14 @@ Returns (t1, t2, theta_points, theta_weights).
423423
"""
424424
function _find_bounce_points_and_grid(
425425
lmda::Float64, bo::Float64, sigma::Int,
426-
B_extrap, theta_bmax::Float64, psi::Float64,
426+
B_vpar, theta_bmax::Float64, psi::Float64,
427427
ntheta::Int
428428
)
429429
if sigma == 0 # trapped
430-
# Bounce points: all roots of v_par(θ) = 1 − (λ/bo)·B_extrap(θ) in (0,1),
430+
# Bounce points: all roots of v_par(θ) = 1 − (λ/bo)·B_vpar(θ) in (0,1),
431431
# sorted descending — the same order as Fortran spline_roots, which the
432432
# marginally-trapped and deepest-well wrap logic below assume.
433-
vpar_fn = θ -> _vpar_from_extrap(B_extrap, lmda, bo, θ)
433+
vpar_fn = θ -> _vpar_from_spline(B_vpar, lmda, bo, θ)
434434
bpts = sort!(Roots.find_zeros(vpar_fn, 0.0, 1.0); rev=true)
435435

436436
nbpts = length(bpts)
@@ -443,7 +443,7 @@ function _find_bounce_points_and_grid(
443443
t1 = bpts[1]
444444
t2 = bpts[1] + 1.0
445445
else
446-
t1, t2 = _find_deepest_well(bpts, B_extrap, lmda, bo)
446+
t1, t2 = _find_deepest_well(bpts, B_vpar, lmda, bo)
447447
end
448448

449449
# Power-law grid refined near bounce points
@@ -463,7 +463,7 @@ end
463463
Find the deepest potential well (largest midpoint v_par) among bounce-point pairs,
464464
handling pairs that wrap through θ = 0/1.
465465
"""
466-
function _find_deepest_well(bpts::Vector{Float64}, B_extrap, lmda::Float64, bo::Float64)
466+
function _find_deepest_well(bpts::Vector{Float64}, B_vpar, lmda::Float64, bo::Float64)
467467
nbpts = length(bpts)
468468
best_vpar = 0.0
469469
best_t1 = 0.0
@@ -477,7 +477,7 @@ function _find_deepest_well(bpts::Vector{Float64}, B_extrap, lmda::Float64, bo::
477477
else
478478
θmid = 0.5 * (bpts[i] + bpts[j])
479479
end
480-
vpar_mid = _vpar_from_extrap(B_extrap, lmda, bo, θmid)
480+
vpar_mid = _vpar_from_spline(B_vpar, lmda, bo, θmid)
481481
if vpar_mid > best_vpar
482482
best_t1 = bpts[i]
483483
best_t2 = bpts[j]
@@ -506,7 +506,7 @@ Ports Fortran torque.F90 lines 674-793.
506506
function _bounce_integrate(
507507
tdt_pts::Vector{Float64}, tdt_wts::Vector{Float64},
508508
lmda::Float64, lnq::Float64, sigma::Int, n::Int, q::Float64, bo::Float64,
509-
tspl, B_extrap, chi1::Float64, ro::Float64,
509+
tspl, B_vpar, chi1::Float64, ro::Float64,
510510
mfac::Vector{Int}, dbob_m_f::Vector{ComplexF64}, divx_m_f::Vector{ComplexF64},
511511
divxfac::Float64, wdfac::Float64,
512512
do_matrices::Bool, mpert::Int,
@@ -550,9 +550,9 @@ function _bounce_integrate(
550550
jac = tspl_f[4]
551551
djdpsi = tspl_f[5]
552552

553-
# v_par from the endpoint-fit cubic (consistent with the bounce points);
553+
# v_par from the periodic cubic (consistent with the bounce points);
554554
# the periodic tspl B_val remains the numerator field in the integrands.
555-
vpar = 1.0 - (lmda / bo) * B_extrap(θmod)
555+
vpar = 1.0 - (lmda / bo) * B_vpar(θmod)
556556

557557
if vpar <= 0
558558
# Negative v_par near a bounce point: same fill rules as the Fortran bounce loop.

src/KineticForces/Torque.jl

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,12 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int,
9494

9595
# Create periodic interpolant for poloidal quantities
9696
tspl = cubic_interp(xs, Series(hcat(B_vals, dBdpsi_vals, dBdtheta_vals, jac_vals, djdpsi_vals)); bc=PeriodicBC())
97-
# v_par and the bounce points use a separate endpoint-fit (non-periodic) cubic
98-
# of B, like Fortran's vspl. The endpoint fit of 1−(λ/bo)B equals 1−(λ/bo)
99-
# times the fit of B, so one B_extrap per surface serves every λ.
100-
B_extrap = cubic_interp(xs, B_vals; bc=CubicFit())
97+
# v_par and the bounce points use a separate scalar cubic of B (Fortran's vspl).
98+
# 1−(λ/bo)B is periodic on the closed θ interval, so the fit must be periodic too:
99+
# a non-periodic endpoint fit is only C⁰ at the θ=0/1 seam and manufactures false
100+
# near-seam extrema and root pairs there. The fit of 1−(λ/bo)B equals 1−(λ/bo)
101+
# times the fit of B, so one B_vpar per surface serves every λ.
102+
B_vpar = cubic_interp(xs, B_vals; bc=PeriodicBC())
101103

102104
bmax = maximum(B_vals)
103105
ibmax = argmax(B_vals)
@@ -228,7 +230,7 @@ function tpsi!(tpsi_var::Ref{ComplexF64}, psi::Float64, n::Int, l::Int,
228230
method, op_wmats;
229231
chi1=intr.chi1, ro=intr.ro, mfac=intr.mfac,
230232
mpert=intr.mpert, theta_bmax=theta_bmax,
231-
B_extrap=B_extrap,
233+
B_vpar=B_vpar,
232234
smat=smat_f, tmat=tmat_f, xmat=xmat_f,
233235
ymat=ymat_f, zmat=zmat_f,
234236
energy_atol=atol_xlmda, energy_rtol=rtol_xlmda,
@@ -403,7 +405,7 @@ function calculate_gar(psi, n, l, q, epsr, wdian, wdiat, welec, nuk, bo,
403405
bmax, bmin, n_s::Float64, T_s::Float64, mass, chrg, tspl,
404406
dbob_m_f, divx_m_f, divxfac, wdfac, method, op_wmats;
405407
chi1::Float64, ro::Float64, mfac::Vector{Int}, mpert::Int,
406-
theta_bmax::Float64, B_extrap,
408+
theta_bmax::Float64, B_vpar,
407409
smat=nothing, tmat=nothing, xmat=nothing,
408410
ymat=nothing, zmat=nothing,
409411
nlmda::Int=128, ntheta::Int=128,
@@ -417,7 +419,7 @@ function calculate_gar(psi, n, l, q, epsr, wdian, wdiat, welec, nuk, bo,
417419
# Bounce-averaged quantities per pitch angle
418420
bounce = compute_bounce_data(
419421
psi, n, l, q, bo, bmax, bmin, theta_bmax,
420-
tspl, B_extrap, mfac, chi1, ro, dbob_m_f, divx_m_f, divxfac, wdfac,
422+
tspl, B_vpar, mfac, chi1, ro, dbob_m_f, divx_m_f, divxfac, wdfac,
421423
mass, chrg, T_s, method;
422424
nlmda, ntheta, smat, tmat, xmat, ymat, zmat)
423425

@@ -617,8 +619,9 @@ function _setup_surface_state(
617619
end
618620

619621
tspl = cubic_interp(xs, Series(hcat(B_vals, dBdpsi_vals, dBdtheta_vals, jac_vals, djdpsi_vals)); bc=PeriodicBC())
620-
# Endpoint-fit (non-periodic) cubic of B for v_par and bounce points (Fortran vspl equivalent).
621-
B_extrap = cubic_interp(xs, B_vals; bc=CubicFit())
622+
# Periodic cubic of B for v_par and bounce points (Fortran vspl equivalent); 1−(λ/bo)B
623+
# is periodic on the closed θ interval, so a non-periodic fit would break at the seam.
624+
B_vpar = cubic_interp(xs, B_vals; bc=PeriodicBC())
622625

623626
bmax = maximum(B_vals)
624627
ibmax = argmax(B_vals)
@@ -687,7 +690,7 @@ function _setup_surface_state(
687690

688691
return (;
689692
chrg, mass,
690-
tspl, B_extrap, bmax, bmin, theta_bmax,
693+
tspl, B_vpar, bmax, bmin, theta_bmax,
691694
q, n_s, T_s, welec,
692695
wdian, wdiat, wtran, wgyro, nuk,
693696
epsr,
@@ -752,7 +755,7 @@ function kinetic_energy_matrices_for_euler_lagrange!(
752755

753756
bounce = compute_bounce_data(
754757
psi, n, l, state.q, bo, state.bmax, state.bmin, state.theta_bmax,
755-
state.tspl, state.B_extrap, mfac, chi1, ro, dbob_m_f, divx_m_f, 1.0, wdfac,
758+
state.tspl, state.B_vpar, mfac, chi1, ro, dbob_m_f, divx_m_f, 1.0, wdfac,
756759
state.mass, state.chrg, state.T_s, "fwmm";
757760
nlmda, ntheta, smat=smat_f, tmat=tmat_f, xmat=xmat_f, ymat=ymat_f, zmat=zmat_f)
758761

0 commit comments

Comments
 (0)