Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
14a68ca
feat(fluxsurfaces): add _refine_extremum 2x2 Newton extremum solver
mgyoo86 Jun 23, 2026
4ea1c66
feat(fluxsurfaces): implement bounded refinement for extremum recover…
mgyoo86 Jun 23, 2026
8138bce
refactor(fluxsurfaces): extract cubic-interpolant Newton refinement i…
mgyoo86 Jun 23, 2026
ceef01c
feat(refine_extremum): enhance _refine_extremum with magnetic axis pa…
mgyoo86 Jun 23, 2026
90aa8af
feat(fluxsurfaces): add _project_to_level Newton corrector for cubic …
mgyoo86 Jun 23, 2026
1aaeb98
feat(fluxsurfaces): add contour tangent and curvature primitives
mgyoo86 Jun 23, 2026
4114d68
feat(fluxsurfaces): add Hessian-osculating predictor-corrector step
mgyoo86 Jun 23, 2026
7f42307
feat(fluxsurfaces): add curvature-based contour step control
mgyoo86 Jun 23, 2026
ca69dc3
feat(fluxsurfaces): add predictor-corrector closed-contour tracer
mgyoo86 Jun 23, 2026
674d8d2
feat(fluxsurfaces): add uniform-arclength contour resampling
mgyoo86 Jun 23, 2026
b3b4071
feat(fluxsurfaces): add adaptive-RK4 baseline stepper
mgyoo86 Jun 23, 2026
8cfc164
feat(fluxsurfaces): add :rk4 tracer method and PC/RK4/Contour benchmark
mgyoo86 Jun 23, 2026
b4efb81
feat(fluxsurfaces): add outboard-midplane seed finder
mgyoo86 Jun 23, 2026
2923f39
feat(fluxsurfaces): add single-surface trace_surface_cubic (seed+trac…
mgyoo86 Jun 23, 2026
978b2b3
test(fluxsurfaces): A/B cubic-vs-Contour geometry check + isolation g…
mgyoo86 Jun 23, 2026
1b5b264
feat(fluxsurfaces): add batch trace_surfaces_cubic + flux-surface-ave…
mgyoo86 Jun 23, 2026
6ec8ad3
feat(fluxsurfaces): add X/O critical-point locator and classifier
mgyoo86 Jun 23, 2026
02238fa
feat(fluxsurfaces): add near-critical-point guard for near-separatrix…
mgyoo86 Jun 23, 2026
48b2ad9
fix(fluxsurfaces): strengthen resampler + X-point guard (audit 6.1, 1…
mgyoo86 Jun 23, 2026
18ee9f8
test(fluxsurfaces): strengthen cubic-tracer tests per audit (7.1,8.1,…
mgyoo86 Jun 23, 2026
87a30f8
docs(fluxsurfaces): correct reorder convention to CW in trace_surface…
mgyoo86 Jun 23, 2026
c2fafa0
fix(fluxsurfaces): return closed FluxSurface from cubic tracer (MXH-c…
mgyoo86 Jun 23, 2026
1e0d4e8
feat(fluxsurfaces): add trace_surfaces drop-in mirror + X-point-aware…
mgyoo86 Jun 23, 2026
5085848
perf(fluxsurfaces): replace Optim/Contour extrema refine with in-plac…
mgyoo86 Jun 24, 2026
7abd57e
refactor(fluxsurfaces)!: drop unused BR/BZ args from trace_surfaces
mgyoo86 Jun 24, 2026
014fe3a
perf(fluxsurfaces): single-pass fluxsurface_extrema instead of 4x fin…
mgyoo86 Jun 24, 2026
908c78a
refactor(fluxsurfaces): make Newton extrema refine backend-agnostic
mgyoo86 Jun 24, 2026
01ad835
perf(physics): integer exponents (^2) instead of float (^2.0) in hot …
mgyoo86 Jun 24, 2026
66fb3ea
refactor(fluxsurfaces): move Interpolations backend to a package exte…
mgyoo86 Jun 24, 2026
8b876f3
refactor(fluxsurfaces): optimize trace_surfaces with AdaptiveArrayPoo…
mgyoo86 Jun 24, 2026
6e7bd63
refactor(fluxsurfaces): remove dead _extrema_index/_extrema_cost
mgyoo86 Jun 24, 2026
89320cd
refactor(fluxsurfaces): improve extremum refinement fallback to origi…
mgyoo86 Jun 25, 2026
901f757
refactor(deps): update SimpleNonlinearSolve version constraint to 2
mgyoo86 Jun 25, 2026
2791120
fix(fluxsurfaces): robust X-point-aware extrema refine
mgyoo86 Jun 25, 2026
2e91056
test(fluxsurfaces): robust refine arrives from arbitrary/bad seeds
mgyoo86 Jun 25, 2026
0e9e9c8
fix(fluxsurfaces): clamp refine search to the ψ grid domain
mgyoo86 Jun 25, 2026
de1653a
fix(fluxsurfaces): bound Z-extremum refine to the confined side of th…
mgyoo86 Jun 25, 2026
370596e
revert: drop the X-point Z-bound (too strong); keep the 2-D dot test
mgyoo86 Jun 25, 2026
c5927f0
perf(fluxsurfaces): split residual/Hessian eval in robust refine Newton
mgyoo86 Jun 25, 2026
ff567f3
refactor(fluxsurfaces): retire the mirror refine; one globalized Newt…
mgyoo86 Jun 25, 2026
3d041e7
Merge branch 'master' into feat/refine_fluxsurface
mgyoo86 Jun 25, 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
11 changes: 10 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Orso Meneghini <orso82@gmail.com>"]

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
AdaptiveArrayPools = "4f381ef7-9af0-4cbe-99d4-cf36d7b0f233"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Contour = "d38c429a-6771-53c6-b99e-75d170b6e991"
CoordinateConventions = "7204ce3a-f536-43d2-be4a-fbed74e90d86"
Expand Down Expand Up @@ -43,8 +44,15 @@ SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[weakdeps]
Interpolations = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"

[extensions]
IMASInterpolationsExt = "Interpolations"

[compat]
AbstractTrees = "0.4"
AdaptiveArrayPools = "0.3.6"
Compat = "4.10"
Contour = "0.6"
CoordinateConventions = "1"
Expand All @@ -58,6 +66,7 @@ Graphs = "1"
HelpPlots = "1.1"
IMASdd = "8.3"
IMASutils = "1.5.1"
Interpolations = "0.13, 0.14, 0.15, 0.16"
Jedis = "0.3"
LaTeXStrings = "1"
Measurements = "2"
Expand All @@ -76,7 +85,7 @@ Random = "1.11.0"
Ratios = "0.4"
RecipesBase = "1"
Roots = "2, 3"
SimpleNonlinearSolve = "2.12.0"
SimpleNonlinearSolve = "2"
StaticArrays = "1"
Statistics = "1.11.1"
julia = "1"
23 changes: 23 additions & 0 deletions claudedocs/cubic_tracer_benchmark.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# PC vs adaptive-RK4 vs Contour.jl: drift, point count, timing on DIII-D closed surfaces.
# Scratch diagnostic (not a pass/fail test).
import IMAS
using Printf

filename = joinpath(pkgdir(IMAS.IMASdd), "sample", "D3D_eq_ods.json")
dd = IMAS.json2imas(filename; show_warnings=false)
eqt = dd.equilibrium.time_slice[1]
eqt2d = IMAS.findfirst(:rectangular, eqt.profiles_2d)
r, z, itp = IMAS.ψ_interpolant(eqt2d)
RA, ZA = eqt.global_quantities.magnetic_axis.r, eqt.global_quantities.magnetic_axis.z
psi_axis = itp(RA, ZA)
eqt1d = eqt.profiles_1d
# a mid-radius closed level
c = psi_axis + 0.5 * (eqt1d.psi[end] - psi_axis)
seed = (maximum(r) - 1e-3, ZA) # outboard; project finds the surface
seed = IMAS._project_to_level(itp, c, seed)[1]

for method in (:pc, :rk4)
t = @elapsed (Rs, Zs, closed) = IMAS._trace_surface_cubic(itp, c, seed; method)
drift = maximum(abs(IMAS.FI.value_gradient(itp,(Rs[k],Zs[k]))[1]-c) for k in eachindex(Rs))
@printf("%-5s closed=%s N=%4d drift=%.2e t=%.2f ms\n", method, closed, length(Rs), drift, t*1e3)
end
18 changes: 18 additions & 0 deletions ext/IMASInterpolationsExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module IMASInterpolationsExt

import IMAS
import Interpolations

# Interpolations.jl backend for the generic interpolant helpers in IMAS (src/physics/fields.jl).
# Active only when Interpolations is loaded. It uses positional coords and returns SVector/SMatrix,
# which index like the FastInterpolations NTuple/Matrix the IMAS math expects.
@inline IMAS._gradient(itp::Interpolations.AbstractInterpolation, r, z) =
Interpolations.gradient(itp, r, z)

@inline IMAS._value_gradient(itp::Interpolations.AbstractInterpolation, r, z) =
(itp(r, z), Interpolations.gradient(itp, r, z))

@inline IMAS._hessian!(H, itp::Interpolations.AbstractInterpolation, r, z) =
(H .= Interpolations.hessian(itp, r, z); H)

end
1 change: 1 addition & 0 deletions src/IMAS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ using Printf
using Compat:@compat
import OrderedCollections
import FastInterpolations as FI
using AdaptiveArrayPools
const document = OrderedCollections.OrderedDict()

macro import_all(mod)
Expand Down
1 change: 1 addition & 0 deletions src/physics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ include(joinpath("physics", "tf.jl"))
include(joinpath("physics", "currents.jl"))
include(joinpath("physics", "fields.jl"))
include(joinpath("physics", "fluxsurfaces.jl"))
include(joinpath("physics", "fluxsurfaces_cubic.jl"))
include(joinpath("physics", "rf.jl"))
include(joinpath("physics", "neoclassical.jl"))
include(joinpath("physics", "profiles.jl"))
Expand Down
13 changes: 8 additions & 5 deletions src/physics/fields.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import SimpleNonlinearSolve

document[Symbol("Physics fields")] = Symbol[]

# gradient of a ψ interpolant: FI gets the native fast path,
# the open version is for users still passing an Interpolations.jl interpolant
@inline _psi_gradient(itp::FI.AbstractInterpolant, r, z) = FI.gradient(itp, (r, z))
@inline _psi_gradient(itp, r, z) = parentmodule(typeof(itp)).gradient(itp, r, z)
# Analytic gradient / value+gradient / Hessian of a ψ interpolant, dispatched on the backend.
# FastInterpolations gets the native in-place fast path here; other backends (e.g. Interpolations.jl)
# are added by package extensions, loaded only when that backend is (see ext/IMASInterpolationsExt.jl).
# Results are indexed g[1]/g[2] and H[i,j], so any backend returning indexable values works.
@inline _gradient(itp::FI.AbstractInterpolant, r, z) = FI.gradient(itp, (r, z))
@inline _value_gradient(itp::FI.AbstractInterpolant, r, z) = FI.value_gradient(itp, (r, z))
@inline _hessian!(H, itp::FI.AbstractInterpolant, r, z) = FI.hessian!(H, itp, (r, z))

"""
Br_Bz(eqt2d::IMAS.equilibrium__time_slice___profiles_2d)
Expand All @@ -30,7 +33,7 @@ end
Br_Bz(PSI_interpolant, r::T, z::T) where {T<:Real}
"""
function Br_Bz(PSI_interpolant, r::T, z::T) where {T<:Real}
grad = _psi_gradient(PSI_interpolant, r, z)
grad = _gradient(PSI_interpolant, r, z)
inv_twopi_r = 1.0 / (2π * r)
Br = grad[2] * inv_twopi_r
Bz = -grad[1] * inv_twopi_r
Expand Down
Loading
Loading