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:
- evolve the moving-frame
[θ, z]trajectory (MovingFrameUPDE); - decide phase-and-spatial lock over the trajectory (
MergeWindowMonitor); - certify the sampled kinematic-safety envelope (
KinematicSafetyCertificate); - check the capacitor bank can deliver the requested compression pulse;
- 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¶
- Evolve the chamber-fixed
[theta, z]trajectory with the MIF-002 moving-frame UPDE (:func:scpn_mif_core.kinematic.evaluate_moving_frame_upde). - Decide phase-and-spatial lock with the MIF-003 merge-window monitor
(:func:
scpn_mif_core.kinematic.evaluate_merge_window_trace). - Certify the MIF-011 sampled kinematic safety envelope over the whole
approach (:func:
scpn_mif_core.kinematic.certify_positions_sampled_kinematic_safety). - Check the MIF-005 capacitor bank can deliver the requested compression pulse
(:meth:
scpn_mif_core.lifecycle.CapacitorBank.feasibility). - 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.