Skip to content

Merge-trigger orchestrator

evaluate_merge_trigger is the end-to-end entry point: it composes the MIF-owned kinematic, safety, capacitor-bank, and Faraday-recovery surfaces into a single fire/abort/hold decision for one FRC merge. It is the function a caller reaches for first (from scpn_mif_core import evaluate_merge_trigger); the examples/frc_merge_trigger.py and scpn-mif demo paths drive it.

Decision pipeline

A MergeTriggerScenario is evaluated in order:

  1. evolve the moving-frame [θ, z] trajectory (MovingFrameUPDE);
  2. decide phase-and-spatial lock over the trajectory (MergeWindowMonitor);
  3. certify the sampled kinematic-safety envelope (KinematicSafetyCertificate);
  4. check the capacitor bank can deliver the requested compression pulse;
  5. optionally estimate Faraday energy recovery for the prescribed expansion.

The outcome is one MergeTriggerOutcome:

Outcome Meaning
FIRE locked, safe, and the bank can deliver the pulse
ABORT_UNSAFE the kinematic-safety envelope was violated
ABORT_BANK_INFEASIBLE locked and safe, but the bank cannot deliver the pulse
HOLD_NO_LOCK no merge-window lock was achieved

Safety dominates: an unsafe trajectory aborts regardless of lock or bank state.

Ownership boundary

This orchestrator wires only MIF-owned surfaces. The self-consistent expansion and compression physics behind the prescribed inputs is owned by SCPN-FUSION-CORE; the Faraday-recovery surface stays upstream-pending until that coupling (FUS-C.6) lands. The orchestrator never reconstructs plasma equilibrium or solves the Hall-MHD/MRTI physics itself.

Python API

merge_trigger

End-to-end FRC merge-trigger decision over the MIF-owned surfaces.

This module composes the per-domain MIF kernels into a single runnable decision: given two counter-propagating FRC plasmoids and the pulsed-shot hardware envelope, should the compression trigger fire at the chamber centre?

Pipeline

  1. Evolve the chamber-fixed [theta, z] trajectory with the MIF-002 moving-frame UPDE (:func:scpn_mif_core.kinematic.evaluate_moving_frame_upde).
  2. Decide phase-and-spatial lock with the MIF-003 merge-window monitor (:func:scpn_mif_core.kinematic.evaluate_merge_window_trace).
  3. Certify the MIF-011 sampled kinematic safety envelope over the whole approach (:func:scpn_mif_core.kinematic.certify_positions_sampled_kinematic_safety).
  4. Check the MIF-005 capacitor bank can deliver the requested compression pulse (:meth:scpn_mif_core.lifecycle.CapacitorBank.feasibility).
  5. Optionally estimate the MIF-009 Faraday energy recovery for a prescribed post-burn expansion trajectory (:func:scpn_mif_core.physics.evaluate_faraday_recovery).

The decision is the instability-preemption gate: an axial-separation envelope violation aborts the shot before the merge can drive an n = 1 tilt, while a locked, safe, bank-feasible approach fires the compression trigger.

Ownership boundary

Every kernel above is MIF-owned. The self-consistent expansion physics (radius, field, and field-rate evolution feeding step 5) is owned by SCPN-FUSION-CORE (FUS-C.6). This pipeline therefore consumes a prescribed expansion trajectory for the recovery estimate rather than evolving compression dynamics locally; the plasma temperature and fusion-power telemetry that the MIF-004 pulsed-shot FSM gates on likewise originate in the physics layer and are not synthesised here.

MergeTriggerOutcome

Bases: StrEnum

Decision emitted by the merge-trigger pipeline.

ExpansionTrajectory(time_s, radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s) dataclass

Prescribed post-burn expansion trajectory for the recovery estimate.

These channels are owned by the physics layer (SCPN-FUSION-CORE FUS-C.6) and are supplied to the pipeline as explicit, externally prescribed inputs; this module does not evolve compression dynamics.

Parameters

time_s : ArrayLike Strictly increasing sample times in seconds, at least two samples. radius_m : ArrayLike Separatrix radius R_s per sample in metres, strictly positive. radial_velocity_m_s : ArrayLike Radial expansion velocity dR_s/dt per sample in metres per second. magnetic_field_T : ArrayLike External confining field B_ext per sample in tesla. magnetic_field_rate_T_s : ArrayLike Field rate dB_ext/dt per sample in tesla per second.

MergeTriggerScenario(moving_frame, initial_phases_rad, initial_positions_m, velocities_m_s, dt_s, steps, merge_window, safety, bank, bank_initial_voltage_V, compression_pulse, recovery=None, expansion=None) dataclass

Typed input bundle for a single FRC merge-trigger evaluation.

Parameters

moving_frame : MovingFrameUPDESpec Chamber-fixed moving-frame UPDE parameter set (carries the underlying Doppler-Kuramoto phase law). initial_phases_rad, initial_positions_m, velocities_m_s : ArrayLike Initial per-oscillator phases (rad), axial positions (m), and constant axial velocities (m/s). Each must match moving_frame.n_oscillators. dt_s : float Fixed integration step in seconds, strictly positive. steps : int Number of integration steps, strictly positive. merge_window : MergeWindowSpec Phase/spatial merge-window tolerances. safety : KinematicSafetySpec Sampled kinematic safety envelope (MIF-011). bank : CapacitorBankSpec Capacitor-bank specification (MIF-005). bank_initial_voltage_V : float Initial bank voltage in volts; 0 <= V <= bank.voltage_max_V. compression_pulse : PulseSpec Requested compression discharge whose feasibility gates the fire decision. recovery : FaradayRecoverySpec or None, optional Recovery-coil specification. Required to produce a recovery estimate. expansion : ExpansionTrajectory or None, optional Prescribed expansion trajectory for the recovery estimate. Both recovery and expansion must be present for the estimate to run.

__post_init__()

Validate cross-surface scenario shapes before trigger evaluation.

MergeTriggerReport(outcome, reason, lock_achieved, first_lock_time_s, min_separation_m, max_abs_separation_m, safety_passed, safety_first_violation_index, bank_feasible, bank_feasibility_reason, bank_available_energy_J, recovered_energy_J, peak_recovered_power_W, kinematic_report, merge_trace, safety_certificate, recovery_report) dataclass

Typed result of a merge-trigger evaluation.

Attributes

outcome : MergeTriggerOutcome The fire/abort/hold decision. reason : str Human-readable explanation of the decision. lock_achieved : bool Whether the merge window reached phase-and-spatial lock. first_lock_time_s : float or None Time of first sustained lock, or None if never locked. min_separation_m, max_abs_separation_m : float Minimum axial separation reached and the maximum absolute separation against the safety reference over the approach. safety_passed : bool Whether the sampled kinematic safety envelope held throughout. safety_first_violation_index : int or None Zero-based index of the first envelope violation, or None. bank_feasible : bool Whether the bank can deliver the requested compression pulse. bank_feasibility_reason : str Feasibility explanation from the capacitor-bank model. bank_available_energy_J : float Stored bank energy at the initial voltage in joules. recovered_energy_J, peak_recovered_power_W : float or None Integrated recovered energy (J) and peak recovered power (W) for the prescribed expansion, or None when no recovery estimate was requested. kinematic_report : MovingFrameUPDEReport Full moving-frame trajectory trace. merge_trace : MergeWindowTrace Full merge-window evaluation trace. safety_certificate : KinematicSafetyCertificate Sampled kinematic safety certificate. recovery_report : FaradayRecoveryReport or None Faraday recovery waveform report, or None.

evaluate_merge_trigger(scenario)

Run the full merge-trigger decision pipeline for one scenario.

Parameters

scenario : MergeTriggerScenario The typed input bundle.

Returns

MergeTriggerReport The decision and the full intermediate evidence.

Notes

The decision precedence is safety first, then lock, then bank feasibility: an envelope violation aborts regardless of lock, because firing into an unsafe approach is the failure this pipeline exists to preempt.

Standards-interop

A FIRE/abort decision can be wrapped in the White-Rabbit-timestamped trigger-I/O contract (sensor-edge → trigger-edge latency, EPICS channels) — see Trigger I/O and examples/interop_bridge.py.