Repository navigation
KineticForces - FEATURE - Rotation prediction: a momentum-balance module fed by tabulated torque surfaces #461
Description
Activity
First concrete piece: #462 stores the torque surface T(ψ, Δω) per correction array under
ErrorFields/NTV/RotationScan/(NaN-padded matrices with a coil dimension), built once byUtilities.adaptive_sample, and solves the 0-D balance on it. Two things learned there that the module should inherit: the kernel's torque sign is such that a positive T_φ brakes the file's co-rotation (encoded as a checked constant), and an adaptive scan scored only against the global range misses a narrow feature on a large background torque, so the sampler also refines intervals whose error is far above the median.Locality check for the torque-surface contract (DIII-D error-field example, #462 branch). The concern: a scalar rotation scan cannot serve a transport solver if the evolved profile changes shape. Test: build the rigid-shift table on seven shifts, then evaluate the kernel once on a deliberately deformed profile (shift growing from zero at the axis to −60 krad/s at the edge, i.e. a different gradient everywhere) and compare its torque density with a lookup in the table at the local rotation value of the deformed profile.
Result: the kernel density on the deformed profile matches the local lookup at correlation 0.9915 with an RMS difference of 2 % of the peak (max 8 %, at the linear-in-shift interpolation resolution of 15 krad/s), and the integrated torque over the compared range agrees to 1.6 %. Treating the deformed profile as a rigid shift is 32 % off with correlation 0.905. So the torque density is a local functional of the profile to within the table's interpolation error, as expected for a bounce-averaged local kinetic response with a rotation-independent ideal plasma response: the rigid shift is only the sampling device, and the surface must be consumed as T′(ψ, ω) looked up at ω(ψ), never as a function of one scalar. Consequences for the contract: store the density (not only the cumulative torque); the shift window at each ψ must cover the local offset there (the current span is sized at the innermost surface, so the solver should check coverage per ψ and request a wider scan when needed); refine the shift grid on the density profile, not the total, when building a surface for transport use; and keep the ψ grid fine enough to resolve the kinetic resonance panels, which move with the profile. Half of this example's torque sits at ψ_N > 0.95, so the edge treatment (#315) is not a detail.
Starting point for the density surface: commits 874d4b9 and 710c573 (on the #462 branch history, removed from the branch to keep that PR simple) add
torque_full_density/torque_residual_densitytoEFCCoupling, the driver, the HDF5 writer and reader, and the tests. Cherry-pick them onto the module's branch when it starts; they were passing the NTV and error-field tests.Design principle (from discussion): stationary solvers only, no time-marching. The module is a nonlinear stationary solver over tabulated torque surfaces, not a transport code.
- Offset profile: the zero of T′(ψ, ω) in ω at each ψ, read off the map by interpolation. No balance needed.
- 1-D momentum balance: a nonlinear two-point boundary value problem with the tabulated source; solve by Newton iteration with the Jacobian from ∂T′/∂ω of the interpolant (tridiagonal solves). This is the TGYRO-style flux-matching approach to stationary transport, not a run to steady state.
- Thresholds and bifurcations: pseudo-arclength continuation in the 3D-field amplitude (or coil current) with fold detection (singular Jacobian) gives the braking bifurcation and both branches, rotating and braked; a time-marched solve only finds the attractor of its initial state. The ErrorFields - FEATURE! - Tabulate the correction-coil NTV torque against rotation and solve a torque balance #462 scalar balance is the degenerate case (losing its root).
- b_crit: the Cole–Fitzpatrick critical field is a fold of the stationary torque balance at the rational surface (residual and its ω-derivative both zero): Newton on the pair, or continuation in the field. With the profile-consistent balance the restoring torque is the 1-D solution's response to a localized sink at the surface; same fold detection. No time advance.
- Globalization: pseudo-transient continuation (implicit steps with growing step size converging to Newton) only as a safeguard when Newton fails from a poor guess; never the physics answer.
- Parallelism: scan points are independent kinetic evaluations; distribute them across processes (the kernel threads internally, so nesting is out). ErrorFields - FEATURE! - Tabulate the correction-coil NTV torque against rotation and solve a torque balance #462 runs them sequentially.
Time-dependent evolution is deliberately out of scope; if a question ever needs it, it is an optional path on the same surfaces.
Interpolant decision: cubic FastInterpolations splines throughout, consistent with the rest of the code base. The torque surface is stored on its grids and consumed through
cubic_interpin the rotation direction (deriv1supplies ∂T′/∂ω for Newton and for the restoring-slope check); #462 switches its own lookups, zero crossings and profile resampling to the same splines.
Why
Several questions we want the code to answer are the same computation seen from different sides:
~2·ω_*Testimate?ErrorFields; its current form assumes torque ∝ rotation far from the offset and a positive torque).Tearing.CriticalResonantField, Tearing - FEATURE - Add critical resonant field calculations to the tearing workflow #415, SLAYER based b_crit calculations need to be ported #371, Tearing.CriticalResonantField - Improve pole avoidance, input options, and grid refinement #416): the layer's rotation should come from a momentum balance that includes the 3D-field torques, not only from the unperturbed profile.All of these are a momentum balance with torque sources that depend on the rotation they act on. The torque sources are expensive (a kinetic torque evaluation is minutes); the balances are cheap. If a transport or balance solver calls the kinetic solve at every iteration or time step the whole thing is unusable, so the framework has to separate the two from the start.
Principle: torque surfaces, evaluated once, consumed by any solver
Every torque source publishes the same object:
built once per perturbation by scanning the rotation with an adaptive sampler (the NTV torque has sharp features: the superbanana-plateau resonance near ω_E ≈ 0, bounce-harmonic resonances, the offset crossing; a fixed grid misses them or wastes evaluations). Solvers interpolate the surface and never call the physics kernel. Sources add: NTV now, resonant EM later, each its own surface with the same contract. Amplitude scaling is quadratic, so a surface per unit current serves any current.
The kinetic torque already returns the ψ-resolved cumulative torque (
torque_profile) and theKineticProfileSplinescontainer has a vector constructor, so a rigid shift of ω_E with the diamagnetic terms held fixed is a few lines; that is the scan variable for NTV (braking changes E×B, not ω_*). The sign convention between T_φ and the rotation it acts on must be a named constant with a runtime check (a restoring torque has negative slope at its zero crossing), never an assumption.Proposed home
A new module after
KineticForcesandTearingand beforeAnalysis, working nameMomentumBalance(orTransport; naming is open). It owns the balance solvers and theTorqueSurfacetype; it does not compute torques. Pieces that belong elsewhere:Utilities.AdaptiveSampling: the generic adaptive 1-D sampler (vector-valued function, initial grid, refinement on curvature and sign change, deterministic, point cap). Reusable for every rotation scan and for any other sharp-feature scan.Equilibrium.KineticProfiles:shift_exb_rotation(profiles, Δ).omega_tor,chi_e,chi_phi, and Tearing - FEATURE - Add critical resonant field calculations to the tearing workflow #415 addedviscous_input_type/viscous_input(profile, scalar, or Prandtl number) to the Tearing control, with reviewers asking for a scalar τ_φ interface. Propose one resolver shared byTearing.CriticalResonantFieldandMomentumBalance: profile column → scalar χ_φ → scalar τ_φ (converted to a flat χ_φ from the momentum content) → fallback to χ_e, so both consumers see the same χ_φ(ψ).MomentumBalance/group ingpec.h5(predicted rotation profiles, offset profile, the torque surfaces with their provenance), annotated per the HDF5 conventions.Initial capabilities, ranked
Δ·T_0/ω_ref = T(Δ)·I²solved for the rotation shift; threshold scaling with an exponent; loss of the root as the braking bifurcation. Acceptance: reduces exactly to the linear-budget model when the torque is constant; the DIII-D error-field example shows the torque crossing zero inside the scanned span.T′(ψ, Δ)in Δ at each ψ, with the rough~2·ω_*Testimate reported next to it. Acceptance: the offset lies inside the scan span everywhere the torque density is non-negligible.−(1/V′) d/dψ [V′ n m ⟨R²⟩ χ_φ |∇ψ|² dω/dψ] = Σ sourceswith the NTV surface as source, χ_φ from the shared resolver, sources from an input torque profile or the unperturbed rotation, and the edge rotation as boundary condition. Outputs the predicted ω(ψ) with and without the 3D field. Acceptance: with zero 3D field it returns the input profile; with a surface that is linear in Δ it matches the analytic solution.CriticalResonantField.Open questions
Related: #415, #371, #416, #423 (ψ-resolved torque response profiles), #315, #401, #370, #333.