Repository navigation
Equilibrium - BUGFIX - Build F and P values in sq spline from FF′ and p′ information - #297
StuartBenjamin wants to merge 26 commits into
Conversation
…explitcit indexing control to match Zeff spline assignment
…r frame VACUUM runs on a theta-reversed boundary, so wv comes back complex-conjugated relative to wp; conjugate it after mscvac (free_run and free_wvmats). The eigenvector norm used jmat(jpert-ipert), the transpose of the plasma-matrix index order; use jmat(ipert-jpert). Up-down symmetric cases are unchanged; asymmetric ones no longer depend on the theta origin.
…er frame Same change as DCON: conjugate wv after mscvac (free_run and free_get_wvac, used by the Galerkin solve) and transpose the norm.
…ier frame STRIDE called mscvac with complex_flag false, keeping only Re(wv), which is itself origin-dependent. Keep the full matrix, conjugate it as in DCON, and transpose the norm.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ler-supplied knot derivatives Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…' and p' (efit, ldp_i)
New equil.in variable profile_source:
values - tabulated f, p; spline-fitted derivatives (default, unchanged)
hermite - tabulated f, p with the tabulated derivatives as knot slopes
integrate - f**2/2 and p integrated inward from the boundary values
(as in Julia GPEC PR #506), tabulated derivatives as slopes
read_eq_efit no longer discards FFPRIM and PPRIME, and fixes an
out-of-bounds index when the g-file has no q profile. read_eq_ldp_i
reads optional trailing FF' and p' records. Falls back to values with a
warning when the derivatives are non-finite or disagree in sign.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nverse sq construction sq_in and sq are fit with spline_fit_hermite so the profile slopes from profile_source are not re-derived by spline differentiation. newq0 rescaling updates the f slope consistently (f' -> f'/ffac). With profile_source = values, output is bit-for-bit unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Against a TokaMaker equilibrium with known profiles, integrate gives F'' errors of 0.1-0.8% (0.1 < psi_n < 0.85) that fall with resolution, where values and hermite give 2-47% that grow with mpsi (single-precision f amplified by differentiation). STRIDE Delta' is correspondingly more consistent across g-file resolutions. Set profile_source="values" to recover the previous behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… end-slope order Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dcon-vacuum-theta-frame) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A second assignment of 4 titles reallocated sq%title, so the dump record was 6 bytes short and read_eq_dump failed (I/O past end of record). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
equil_out_dump appends the supplied-derivative flags with sq%fs1(:,1:2), then eqfun; read_eq_dump reads them when present (older dumps read as before) and no longer fails when the equilibrium is re-read (STRIDE psilim reform). DCON efit -> dump -> dcon reproduces f, mu0p, q, D_I, D_R exactly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bulated data without derivatives Fritsch-Carlson interior slopes with scipy PchipInterpolator's end slopes, so Python front ends (bouquet, TPS) can reproduce GPEC's interpolant exactly. Unit test checks values and derivatives against scipy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…profile table The tabulated Zeff (RDCON MRE terms) and the PENTRC kinetic input table carry pedestal-scale gradients; a cubic spline rings there, pchip does not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Derivative sign taken from f and p together, so a flat p (or f) no longer forces the values fallback; the dump writes eqfun only when it exists; shorter equil.in entry; unit test drops redundant wrappers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tabulated values paired with tabulated derivatives put the values' rounding noise into f'' (the worst option in the comparison). spline_fit_hermite stays, used by integrate to keep the derivatives. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
A flag before this is reviewed: the Julia PR this ports (OpenFUSIONToolkit/GPEC#506) is now parked, and I would not make I ran this branch ( 1. With double-precision files,
2.
At mpsi 512 draw 2 gives +0.15 on 2/1 and +1.5 on 4/1. The cause is the quadrature. Integrating FF′ and p′ needs an assumed shape between nodes (a cubic spline here and in #506). Near steep or kinked pedestal profiles that differs from the file's own F and P. EFIT-family files tabulate Suggestion. Keep I can share the eight g-files and the run script if you want to reproduce it. |
GPEC PR report:
spline_improvements→developThis PR builds on
Zeff_profile_support(PR #296). It fixes an issue identified and fixed by d-burg in Julia GPEC PR #506, using a direct port of that method.spline_improvements, 6 commits on top of0b4a7720, then the merge ofbugfix/dcon-vacuum-theta-frame(viaZeff_profile_support) and 6 more commits (below), the last two from a code review.Generate data behind results: spline_improvements_scripts.zip
Problem
read_eq_efitread the g-file's FFPRIM and PPRIME columns and then threw them away.FFp_error.png).Changes
Each change is its own commit.
spline_fit_hermite(spl, endmode, keep)(equil/spline.f). This is the ordinary fit, except that the caller's knot derivativesfs1are kept for the columns marked inkeep.euler.binare unchanged.New
equil.invariableprofile_source(read_eq.f,global.f,equil.f). It applies toefitand toldp_iwhen the file has FF′ and p′ records. Options:values: the old behaviour (tabulated values, spline-fitted derivatives);integrate: F²/2 and p integrated inward from their boundary values, with the file's derivatives as slopes kept byspline_fit_hermite. This is the method of PR #506.hermite(tabulated values with the file's slopes), was tested and dropped (item 13).Supporting changes:
valuesand prints a warning.read_eq_efitno longer writes out of bounds when the g-file has no q column.read_eq_ldp_ireads optional trailing FF′ and p′ records. These are FF′ = F dF/dψ and p′ in Pa, both against ψ in Wb/rad.direct_runandinverse_runkeep the slopes forsq_inandsq. Thenewq0rescaling updates F′ as F′/ffac. Withprofile_source = "values", the output is bit-for-bit identical to before; this was checked on the TkMkr example'sdelta_prime.out,gsec.bin,gsei.binand the netcdf data.The
sq_outdiagnostic (out_eq_1d) keeps the supplied slopes.The default is
profile_source = "integrate". The evidence is below.regression/spline_tests/contains a unit test (make run) with three checks:"extrap"end slopes converge at 3.2 order;spline_fitgives them.The test fails to link against the old library.
End conditions:
"extrap"needs no change. It is a clamped spline whose end slopes come from a 4-point Lagrange cubic; the end slope is O(h³), as the unit test shows. For F and p the end slopes now come from the file, so"extrap"no longer sets them.pchip and Akima are not used for F and p: they cannot be constrained by derivatives, and once derivatives are supplied they reduce to the same Hermite form. pchip is used for tabulated data without derivatives (item 11).
Evidence
The reference is a TokaMaker equilibrium (
make_truth_equilibrium.py): DIII-D-like, q0 = 1.25, q95 = 4.49. Its FF′ and p′ are dense and smooth, so F, F′, F″ and p′ are known exactly at every ψ. It is written as g-files (129², 257², 513²;efit, direct) and as i-files with FF′ and p′ records (65×129, 129×257, 257×513;ldp_i, inverse). The last surface is at the same true ψ_N = 0.985 in every run.1. F″ against the exact value (
gpec_profiles.py, which reproduces GPEC's sq construction), for the 257-point g-file:Root-mean-square error in F″ for 0.1 < ψ_N < 0.85:
valuesandhermiteget worse as the grid is refined, because the noise in the values is amplified by 1/h².integrateconverges.hermite, which keeps the noisy values alongside exact slopes, is the worst: the values' rounding noise has nowhere to go but F″ inside each interval, about (value error)/h². It was dropped (item 13).2. STRIDE Δ′(2/1),
values/integrate(run_profile_source_comparison.py):integratecuts the spread across the three g-files from 1.43 to 0.96 at mpsi = 256 and from 0.80 to 0.54 at mpsi = 512, and moves them toward the converged value. The remaining scatter comes from the single-precision ψ(R,Z) table, which this PR does not touch.integrateis safe for inverse equilibria and uses the same profile derivatives as the direct path.Effects on results
efitresults change by design. Examples:Further changes
bugfix/dcon-vacuum-theta-frame(0bb9a111, viaZeff_profile_support99378252), It puts the DCON/RDCON/STRIDE vacuum matrix in the plasma's Fourier frame. It merged cleanly.direct_run(822e8b59). A secondsq%titleassignment with 4 entries (gfortran reallocates on assignment) made the dump record 6 bytes short, soeq_type="dump"always failed with "I/O past end of record". That made the dump path unusable before this work.eq_type="dump"keeps the slopes andeqfun(8717d832).equil_out_dumpappendssq_in_slopes(1:2), sq%fs1(:,1:2)and theneqfun%fsafter the old records.read_eq_dumpreads them when present (older dumps read as before) and no longer fails when STRIDE re-reads the equilibrium.eq_type=dumpreproduces f, μ0p, q, D_I and D_R exactly, for bothintegrateandvalues.spline_fit_pchip(de7440b5). Monotone cubic Hermite (Fritsch–Carlson) with scipy's end slopes; the unit test matches scipyPchipInterpolatorto 1e-7.42121c91): the RDCON Zeff profile (mercier.f) and the PENTRC kinetic input table (inputs.f90). Both have pedestal-scale gradients, where a cubic spline rings.7c44ec05):values.equil_out_dumpwriteseqfunonly if it exists.equil.inentry; redundant wrappers removed from the unit test.profile_source = "hermite"dropped (a95a365b). It was the worst option in every comparison above.spline_fit_hermitestays:integrateuses it to keep the derivatives throughsq_in,sq,newq0,sq_outand the dump. Δ′ results unchanged.How to reproduce
The scripts and their inputs ship with this PR as spline_improvements_scripts.zip; its
README.mdlists each script and the commands. In short: