Repository navigation
Equilibrium - FEATURE - Accept supplied Coulomb logarithm and collision rates in kinetic profiles - #627
Conversation
…on rates in kinetic profiles Kinetic files may carry lnLambda, nu_i and nu_e (HDF5 datasets, or a 9-column ASCII table as Fortran PENTRC rates-v1). Each replaces the internal collision model, interpolated in log space; a supplied lnLambda also replaces the resistivity closure's, so KineticForces and the tearing layers see one value. A supplied nu_i is the first main ion's rate, and other species keep the model's (z_s/z_1)^2 sqrt(m_1/m_s) ratio to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
… the toroidal map and B_t Mirrors the corrected Fortran GPEC sign-convention statement: positive omega_E is co-current exactly when B_t is clockwise, not according to helicity alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
… supplied rates meet the closure and scaling factors Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
d6878aa to
a84e973
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
…lper Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
…hort of its tolerance or is not finite The inner QuadGK calls discarded their error estimates, so an integral that stopped at QuadGK's evaluation cap returned its estimate silently; the psi quadrature check sees only the values. Each kind now warns once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
…n so maxlog warnings print once per scan Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
… over any window of surfaces Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
…and how to take one n Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
…eld the real one carries Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
d-burg
left a comment
There was a problem hiding this comment.
Adversarial review at 0404a9028, by model reviewers working from the code and the Fortran v1.6.0 source. I checked items 1, 2 and 5–7 by hand and reran the A15 numbers. Items are marked ran or traced.
What held up: column order and units against inputs.f90; 7- and 8-column files error; the species map and D/T ratios; n/T factors leave supplied ν unscaled, as Fortran; all four closure callers pass one lnΛ, with none left on lnLambda_form; the tolerance formula, zero allocations on the passing path, and thread safety (3 warnings in 20 of 20 repeats); the ω_E direction; the stamp, since src/ is unchanged from d42c17bb4. No tolerance loosens.
To fix here
- Any 9-column ASCII file becomes rates.
KineticProfiles.jl:107goes by column count. Ran: a table with χ values near 1 in columns 7–9 is accepted. Traced: they then act as lnΛ ≈ 1 and ν ≈ 1/s in the torque and η, with no warning. Fortran's defaultlegacyformat ignores those columns, and Julia errored before this PR. #624 called for akinetic_formatkey, so "covers every item" isn't quite true. Suggested fix: add the key next tokinetic_group. - "Closing it drops nothing" doesn't hold. These appear only in #591: the open
_rs_at/_da_dpsi_atnormalization check (Fortran PR 249),qa = qlimnot traced (Fortran PRs 225/234), the direct path not inspected (Fortran PRs 298/335), and the pmodb gauges docs (Fortran PR 339). #632 was closed as covered by #465, which is still open with changes requested. Suggested fix: move them to a v2.1 issue before #591 closes. - One lnΛ feeds both the ion NTV model and the electron η closure, with no opt-out, and no Fortran layer reads it. At n_e = 5e19 and T_e = 1 keV, the NTV form gives 17.65 and the closure gives 15.14, so a PENTRC-style file raises Spitzer η about 17% (traced). The body intends this, but it's a physics decision for the maintainers.
- The harness covers none of this. No case, example or fixture carries rates, so "27 unchanged" says nothing about the feature. The only closure test goes through
layer_eta, so droppinglnLambda=atTearingProblem.jl:64orLayerOverlap.jl:415, orlnLamb=atLayerParameters.jl:290,297, would pass (traced). Also untested:electron=true(KineticProfiles.jl:333), ν_e-only supply, scale factors and an end-to-end torque. Suggested fix: one harness case with a rates file. - Partial supply is silent. At
PlasmaEquilibrium.jl:218, an all-zero column reverts that rate to the model alongside the supplied ones, where Fortran stops (inputs.f90:231-232). Nothing records which rates ran, in the log or ingpec.h5. maxlogis per process, not "per run".check_inner_quadratureis silent on a second failing run in the same session (ran), so a Julia sweep reports only its first failure.- The quiet logger is wider than one scan.
NTVLimits.jl:534spans all coils and both perturbations (:558,:580-581). The warning names no coil, ψ or rotation, andEFCCouplinghas no failure flag (traced).
Open questions
- A15: "no cancellation" isn't shown, because the test data's noise hides it. With exact constant 1e10, end slopes on a uniform 101-point grid are 6.8e-5 and 5.6e-4, and with 3.3e6 they are −3.1e-8 and 1.2e-7 (ran). Fortran's PR 308 differences from
fs(0), so it gives 0 (traced). This is within about 3× round-off, so low priority, but #624 says to file upstream in this case. - Exit crash: nothing shows the
free(): invalid pointercame from a native library's cleanup, and there's no backtrace. An earlier out-of-bounds write fits equally. The harness did record it as failed, and the reported numbers are from clean reruns. A--check-bounds=yesrun would help.
Minor
131e17c06andd6878aa26are stale; they're nowa12d936b4and3883dba76.- QuadGK can also stop before the cap:
check_endpoint_roundoffstopped1/(x − π/4)at 1395 evaluations (ran). The check catches this, so only the docstring is wrong. Its non-finite branch is unreachable from QuadGK, as on #625. - With lnΛ supplied and ν absent, a cold edge logs "flooring the Coulomb logarithm" though no floor applies (
KineticProfiles.jl:35). 1.0D+19exponents, legal in Fortran, stop with a misleading "fewer columns" error (ran).perturbed_equilibrium.mdsays five matrices are written, butC_penetrated_area_weighted_fieldis skipped whenffs.bpenis empty. No test covers a custom-window overlap, andruntests_dominant_coupling.jl:118tests the core window in memory, not from the saved file.
This is not an approval. A third-party human reviewer's approval is still required before merge.
…model and trim the new docs
…rithm when kinetic profiles supply one
…format, as Fortran
…d-rates # Conflicts: # src/Equilibrium/KineticProfiles.jl
Release note
e0bb4f7c1. Supplied rates are opt-in and the inner-quadrature check only warns. The new casetj_kinetic_ntv_rateshas its first reference here.kinetic_formatdefaults to"legacy", the 6-column table every existing deck reads.Kinetic profile files can now supply the Coulomb logarithm and the ion and electron collision rates, as HDF5 datasets
lnLambda,nu_iandnu_e, or as a 9-column ASCII table read withkinetic_format = "rates-v1"in[Equilibrium](API keywordformat). They replace the NTV calculation's internal collision model; the tearing layers' resistivity keeps its ownlnLambda_formclosure. This is the Julia counterpart of Fortran GPEC 1.6.0'skinetic_format = "rates-v1".Closes #624: it covers every item, in code or with the evidence below.
Closes #591: this is the last PR of the Fortran 1.6.0 parity series (#625, #626, #627). The feature-parity items #591 listed have their own issues (#622, #629, #630, #633, #429, #623; #628, #631 and #632 were closed as deliberate or covered), and the four unfinished parity checks moved to #640.
What changed
a12d936b43883dba76conventions.mdnow states the laboratory direction of positive ω_E from the toroidal map φ_CCW = −h(2πζ + ν) used bysample_boundary_grid: positive ω_E is co-current exactly when B_t is clockwise, whatever the helicity. Fortran made the same correction. Julia's ℓ_eff = ℓ + nq already had Fortran's corrected sign.a84e9731d25033d47echeck_inner_quadraturewarns once per integral kind and Julia session when a pitch or energy integral stops short of its tolerance or is not finite; see below.d42c17bb4maxlogwarning prints once per scan rather than once per scan point.0787c5ebb,da929129f83396e096f5b64a9333ede86983kinetic_formatselects the ASCII layout, so a 9-column file is no longer read as rates by its column count alone. The column count must match the format.0ed35062ctj_kinetic_ntv_rates; see below.What the supplied rates do
KineticProfileDatafields and HDF5 datasets,lnLambda,nu_iandnu_e, each one row in_KINETIC_H5_PROFILESlikechi_e; the ASCII reader takes Fortran's 9-column table underkinetic_format = "rates-v1".kinetic_profile_splinesandresolve_ntv_species.collisionality_factorstill multiplies them.#624 items closed without code, and the inner-quadrature check
C_resonant_area_weighted_field, which acts on b̃ (the root-area-weighted field), and the overlap V^H·b̃ uses that same basis.test/runtests_dominant_coupling.jl:97already checks thatU * (σ .* overlap)reproduces the solve's resonant field to 1e-8.forcing_overlapcarries units (T), which was PR 185's other point.25033d47e).check_inner_quadraturewarns once per integral kind (pitch, energy, CGL energy) when the error estimate exceedsmax(atol, rtol·|I|), which happens when QuadGK stops at its evaluation cap or on endpoint roundoff, or when the result is not finite.cubic_interp+deriv1end slopes stay within a few times the round-off limit (machine epsilon × offset / grid spacing) up to an offset of 1e10. There is no cancellation like the one Fortran fixed.Regression report
Harness on SDCC (
regress-fanoutrunpr627_2667d1294): #625 ate0bb4f7c1vs this branch at2667d1294.gal_resistive_peis N/A by design (PerturbedEquilibrium - FEATURE - Complete the resistive perturbed-equilibrium workflow from Galerkin and matched results #635).tj_kinetic_ntv_rates: the TJ NTV deck readingkinetic_rates.datas rates-v1, whose lnΛ is the model's and whose ν_i, ν_e are 3× the model's. It fails at Equilibrium/KineticForces - BUGFIX! - Port the Fortran 1.6.0 kinetic profile, bounce-integral and torque-method corrections #625, which has nokinetic_formatkey, as expected, and runs here (75 ψ-quadrature evaluations). A local run confirms the supplied rates take effect: the fgar torque goes from 9.74e-4 to 7.37e-4 N·m againstkinetic.dat.Notes for reviewers
bugfix/fortran-parity-kin), which is merged up to develop2d12b7962. When Equilibrium/KineticForces - BUGFIX! - Port the Fortran 1.6.0 kinetic profile, bounce-integral and torque-method corrections #625 merges GitHub retargets this PR todevelop. @matt-pharr: confirm the base isdevelopbefore merging. "Closes Repo - GPEC 2.0 Fortran parity plan #591" and "Closes Repo - FEATURE - Finish Fortran GPEC 1.6.0 parity: supplied collision rates, overlap check and quadrature accounting #624" only take effect on a PR intodevelop.runtests_multiion100/100 after the Equilibrium/KineticForces - BUGFIX! - Port the Fortran 1.6.0 kinetic profile, bounce-integral and torque-method corrections #625 merge; before it,runtests_slayer_inputs94/94 andruntests_solve_api175/175, including a deck-and-API parity case forkinetic_format.a84e9731d) and adversarially by @d-burg; the fixes for the second review aref5b64a933,3ede86983and0ed35062c, and the four unfinished Repo - GPEC 2.0 Fortran parity plan #591 checks are Repo - Finish the Fortran 1.6.0 parity checks left open at the 2.0.0 release #640.🤖 Generated with Claude Code