Diagnostics registry¶
MHX diagnostics are centralized in mhx.diagnostics so runs, reports,
benchmarks, and future scan/inverse-design workflows use the same definitions.
TOML configs select diagnostics through [diagnostics].quantities:
[diagnostics]
quantities = ["energy", "mode_growth", "divergence_error"]
mode = [1, 1]
fit_time_window = [0.02, 0.1]
Inspect registered diagnostics from the CLI:
mhx diagnostics list
mhx diagnostics list-with-plugins --plugin-module examples.local_extension_plugin
mhx diagnostics list-with-plugins --entry-point-group mhx.diagnostics
Built-in diagnostics¶
Name |
Output keys |
|---|---|
|
|
|
|
|
|
Energy definitions¶
For the current 2D reduced-MHD state variables \(\psi\) and \(\omega=\nabla^2\phi\), MHX computes
The trajectory diagnostic reports final magnetic/kinetic energy and initial/final total energy. The benchmark validation report uses these fields to gate unphysical total-energy growth in the current dissipative FAST benchmark.
Mode growth¶
For a configured Fourier mode \((k_x,k_y)\), MHX stores
The fitted growth/decay rate is the least-squares slope of \(\log A_k(t)\) against time over the configured inclusive window:
This scalar is a reproducibility diagnostic for individual saved trajectories. It is not, by itself, a calibrated FKR eigenmode claim. Calibrated tearing checks live in the separate Harris eigenvalue, dispersion, layer, and time-domain replay gates documented on validation.md.
Reconnected flux and island-width proxies¶
MHX exposes low-level island diagnostics as pure functions rather than default run-summary fields, because a credible nonlinear island claim also needs a resolved separatrix, a calibrated equilibrium shear, and a long enough time window. For a real single-harmonic perturbation
mode_amplitude returns \(|\hat\psi_k|=|\tilde\psi_1|/2\). The helper
reconnected_flux_amplitude(state, mode=...) returns \(2|\hat\psi_k|\), so the
cosine amplitude is recovered exactly for single-mode tests. Given local
magnetic shear \(B_y'(0)\), the Rutherford full-width proxy is
Use island_width_from_mode(state, mode=..., magnetic_shear=...) for quick
post-processing, then gate any publication claim with the nonlinear duration
audit and a resolution/time-step convergence study. The unit tests verify that
the proxy recovers a known cosine amplitude and rejects nonpositive shear.
Divergence error¶
The reduced-MHD perpendicular magnetic field is represented as
so analytically \(\nabla\cdot B_\perp=0\). MHX reports the final spectral consistency check
For smooth periodic fields this should be near roundoff. The unit tests include a spectral-zero gate for this diagnostic.
Flux critical points¶
README media and turbulent-reconnection diagnostics use magnetic-flux critical
points from
mhx.diagnostics.detect_flux_critical_points and
mhx.diagnostics.critical_points_by_kind. The detector finds local minima of
\(|\nabla\psi|\) and classifies them with the Hessian determinant:
Points with \(D<0\) are marked as X-points; points with \(D>0\) are marked as
O-points. Passing refine=True applies one local quadratic Newton correction,
which reduces grid-locking for smooth fields:
mhx.diagnostics.track_critical_points then greedily links detected points
across frames by nearest neighbor and point kind. This is still a validation and
visualization diagnostic rather than a full topological event solver: it does
not model separatrix reconnection events, mergers, or bifurcations.
Source links:
Python extension API¶
Use DiagnosticSpec and DiagnosticsRegistry for new diagnostics:
from mhx.diagnostics import DiagnosticSpec, default_diagnostics_registry
def compute_my_metric(context):
return {"my_metric": 0.0}
registry = default_diagnostics_registry()
registry.register(
DiagnosticSpec(
name="my_metric",
description="Example user metric.",
output_keys=("my_metric",),
compute=compute_my_metric,
)
)
The callable receives a DiagnosticContext with the saved trajectory, initial
state, domain lengths, diagnostic Fourier mode, and fit-time window.
Diagnostics can also provide optional report figures by passing a figure
callable. The hook receives the same DiagnosticContext, the scalar diagnostic
dictionary, and an output directory. It should write deterministic files and
return a mapping from figure key to path:
from pathlib import Path
def plot_my_metric(context, diagnostics, figure_dir: Path):
path = figure_dir / "my_metric.png"
# write figure to path
return {"my_metric_history": path}
registry.register(
DiagnosticSpec(
name="my_metric",
description="Example metric with a report figure.",
output_keys=("my_metric",),
compute=compute_my_metric,
figure=plot_my_metric,
)
)
Config-loaded diagnostics plugins¶
A local module can expose diagnostics without modifying MHX source code:
from mhx.diagnostics import DiagnosticSpec
def compute_metric(context):
return {"my_metric": 0.0}
def register_diagnostics(registry):
registry.register(
DiagnosticSpec(
name="my_metric",
description="Example metric.",
output_keys=("my_metric",),
compute=compute_metric,
)
)
Then enable it in TOML:
[diagnostics]
quantities = ["energy", "mode_growth", "my_metric"]
plugin_modules = ["my_project.mhx_diagnostics"]
Installed packages can alternatively expose diagnostics through the
mhx.diagnostics entry-point group:
[diagnostics]
quantities = ["energy", "mode_growth", "my_metric"]
plugin_entry_point_groups = ["mhx.diagnostics"]
The demo examples/linear_tearing_plugin_demo.toml loads
examples.local_extension_plugin, which registers final_flux_l2. The output
schema records diagnostic_plugin_modules and diagnostic_quantities to keep
extension-derived figures auditable.
mhx report <run-dir> now includes an Additional scalar diagnostics section
for scalar keys that come from plugin diagnostics, for example
final_flux_l2 in the local plugin demo.
Reports also reconstruct diagnostic registry metadata from
config_effective.json. When plugin modules or entry points are still importable
at report time, report.json contains diagnostic_metadata, and report.md
renders a table of selected diagnostic descriptions and output keys. If a plugin
cannot be imported, the report still writes but records a warning.
If a selected diagnostic defines a figure hook, mhx figures <run-dir> writes
the files under figures/diagnostics/. mhx report <run-dir> dispatches the
same hooks and records them in report.json as diagnostic_figures. The local
plugin example writes
figures/diagnostics/final_flux_l2_history.png, which is checked in CI as part
of the FAST artifact pipeline.