PLUME accepts rho_ref and d_ref inputs while retaining the finite-temperature
kinetic calculation in its existing variables. The parameter definitions and a
matched input pair are documented in README.md and input.md.
| Subsystem | Findings |
|---|---|
| Parameter storage and input | src/vars.f90 declares global parameters, the specie type, and scan state. read_in_params and spec_read in src/functions.f90 read ¶ms and indexed species namelists. Validation precedes kinetic evaluation. |
| Reference species | Species 1 supplies the reference anisotropy and reference frame checks. The Python wrapper likewise assumes species 1 is the reference. No new reference selector was introduced. |
| Susceptibility | disp0 and disp1 in src/disprels.f90 implement collisionless and weakly collisional kinetic responses. Both use betap/vtp**2 for the plasma-frequency scale, signed muS/Qs for gyrofrequency, thermal Bessel arguments, and thermal resonance arguments. |
| Dispersion and roots | disp dispatches the susceptibility calculation. map_search, refine_guess, and rtsec use dimensionless frequency omega/Omega_R. The determinant and susceptibility are identical for physically equivalent inputs. |
| Eigenfunctions and heating | calc_eigen uses the wave tensor, susceptibility, and derived thermal state for fields, density, velocity, total heating, and seven resonance heating channels. Its finite-frequency derivative calculation is unchanged. |
| Diagnostics | src/fpc.f90 uses thermal velocities for gyrotropic and Cartesian distributions and correlations. Its file headers describe derived legacy parameters even for a d_ref input. The public single-frequency diagnostic uses the same derived state. |
| Scans | om_scan, om_double_scan, and map_scan mutate input parameters through scan pointers. Their setup helpers cover both wavevectors, magnitude/angle, beta, global velocity, and all six species parameters. read_radial_input reads .rad tables; radial_scan interpolates their values and continues roots through wavevector scans. |
| Python | linfpclib/linfpc.py constructs and reads namelists, computes collision frequencies, and loads numeric outputs. contours/plot_plume_resonances.py interprets temperature widths, drift/resonance velocities, and wavevector labels. |
The existing gyroradius is perpendicular:
rho_R = v_tperp,R / abs(Omega_R). For an anisotropic reference,
Omitting the anisotropy factor changes the physical system when alphS for
species 1 differs from unity. The sign of Qs is retained in cyclotron terms;
plasma-frequency magnitudes use Qs**2.
Temperature-sensitive expressions include the Bessel argument proportional to
1/tauS, the thermal resonance argument, the drift factor
kpar*vvS/sqrt(betap*alpha_R), eigenfunction factors vtp**2/betap, and FPC
factors containing sqrt(tauS/(muS*betap)). None is a cold susceptibility.
Zero and negative kinetic temperatures are rejected before evaluating them.
Approach A was selected for this stage. It requires fewer changes than rewriting both susceptibility kernels and their diagnostics in inertial units, and retains the legacy floating-point expressions. Approach B would avoid a thermal adapter at very small beta and offer a more direct cold-reference path, but would change substantially more numerical code.
The public globals remain the authoritative input state in the chosen
convention. sync_solver_state derives solver_* values before every disp
evaluation. Susceptibility, eigenfunction, and FPC routines read that derived
state. In rho_ref, the adapter copies inputs without changing their values.
In d_ref, it uses
The input state can represent zero temperature independently of a thermal reference length. This release's kinetic adapter deliberately rejects it. A future cold-reference calculation must dispatch before this adapter rather than create a fictitious reference temperature. Extremely small positive beta still inherits the conditioning limits of the legacy thermal calculation.
d_ref beta scans and species-1 temperature scans update both redundant
parameters. Other input values stay fixed. Scanning both independently in a
two-dimensional run is rejected. A legacy beta scan instead holds its legacy
wavevectors, thermal velocity, and temperature ratios fixed. To compare those
physical paths, convert every point, including all affected inputs.
Radial tables use the selected input convention; linear interpolation of
reciprocal temperatures in one convention generally differs from linear
interpolation in the other. Matching endpoints alone does not establish an
identical interpolated physical path.
Kn uses the selected length. With
Kn_d = Kn_rho * sqrt(beta_R*alpha_R), the equivalent collision frequency is
sqrt(muS*tauS_d)/(sqrt(2)*Kn_d). Numeric scan output remains in input units.
FPC output retains its documented derived thermal units. Reusing an output name
for a legacy run removes a stale d_ref metadata file.
Run the available automated suite with:
make -j2
MPLCONFIGDIR=/tmp/plume-mpl python3 -m unittest discover -s tests -p 'test_*.py' -v
The suite compares raw complex determinants, every susceptibility element,
electric/magnetic fields, polarization, density/velocity fluctuations, heating
and all seven heating channels, and converged complex roots. Cases include
isotropic and anisotropic proton/electron plasmas, electron drift, drifting
alpha particles, oblique propagation, and reference beta 1, 0.3, and 0.02.
Root checks also require convergence before the secant iteration limit and a
scaled determinant below 1e-8.
Integration checks cover parallel/perpendicular wavevector scans, two-dimensional scans, frequency maps, beta scans converted point by point, velocity and species-temperature scans, radial interpolation, both FPC coordinate systems, weak collisions, example inputs, Python round trips, input validation, and metadata when an output name is reused.
High-precision comparisons use 1e-10 + 5e-8*max(abs(a),abs(b)). Rounded mode
files use 1e-4*max(1,abs(a),abs(b)); FPC files use their printed precision.
The existing map fixtures contain singular grid points, so the map comparison
requires finite values in its nonsingular test grid.
The completed automated run passes 15 tests. Across the high-precision
equivalence cases, the maximum abs(a-b)/max(1,abs(a),abs(b)) is 4.668e-13;
the maximum absolute difference in a frequency component is 6.939e-18.
The legacy probe comparison is exact. Python compilation and git diff --check
also pass. FORD is not installed in the local environment, so its rendered
documentation build was not run locally; the report is included in the existing
documentation workflow.
Legacy regression builds commit
c6c7616e1fc58eb6118e1f9423a3f0df6d52ef20, the last pre-normalization revision,
and requires exact probe records for two existing input files. The reference
commit is pinned so merging this feature cannot turn the test into a comparison
against itself. Existing expected data files are not modified.
The full-resolution example_map_par.in was also run in isolation during the
initial implementation: its dispersion map and all four mode files matched the
pre-change build byte for byte. The first six .roots columns matched exactly.
Some remaining legacy .roots species columns differ because the old
non-map-scan path writes an uninitialized parameter array. The new d_ref path
initializes those columns. The tracked golden files additionally correspond to
older input ranges and do not reproduce the current example; they were retained.
The initial implementation changed src/vars.f90, src/functions.f90,
src/disprels.f90, src/fpc.f90, linfpclib/linfpc.py, and
contours/plot_plume_resonances.py. It added the Fortran probe, Python test suite,
and matched example pair, and updated README, input/output documentation, FORD
source comments, and .gitignore. This follow-up pins the regression baseline,
extends path coverage, fixes the single-frequency heating array allocation,
aligns Python's beta/temperature tolerance with Fortran, and completes this
report.
The future cold-fluid stage must:
tauS=0 and betap=0 through a path independent of the thermal adapter,
including a fully cold proton/electron plasma.No cold susceptibility has been added in this stage.