Skip to content

API reference

The public Python surface is rendered by mkdocstrings from the docstrings in src/scpn_mif_core/. The public Rust surface is rendered by rustdoc under docs/api/rust/ (built separately via make bridge).

Python

The package root re-exports the full public API of every capability subpackage, so any documented symbol is reachable from the top level (for example from scpn_mif_core import DopplerKuramoto, evaluate_merge_trigger). The subpackages remain importable for domain-scoped use (scpn_mif_core.kinematic).

End-to-end pipeline

scpn_mif_core.merge_trigger.evaluate_merge_trigger composes the MIF-owned kinematic, safety, capacitor-bank, and Faraday-recovery surfaces into a single fire/abort/hold decision for an FRC merge. It evolves the moving-frame [θ, z] trajectory, decides phase-and-spatial lock, certifies the sampled kinematic safety envelope, checks the capacitor bank can deliver the requested compression pulse, and optionally estimates Faraday energy recovery for a prescribed expansion trajectory. The self-consistent expansion physics is owned by SCPN-FUSION-CORE and supplied as an explicit prescribed input.

scpn_mif_core

SCPN-MIF-CORE — Magneto-Inertial Fusion Core.

Deterministic phase synchronisation and hardware synthesis for high-beta pulsed magneto-inertial fusion plasmas on field-reversed configurations.

This module is the curated public surface. It re-exports the full public API of every capability subpackage and the top-level merge-trigger pipeline so a caller can reach any documented symbol from the top level (for example from scpn_mif_core import evaluate_merge_trigger) while the subpackages remain importable for domain-scoped use (scpn_mif_core.kinematic). Hot kernels live under the Rust workspace at scpn-mif-rs/ and are selected transparently by the dispatched_* entry points via the benchmark-ranked dispatch table; the pure-Python reference runs when the extension is absent.

The dispatched_* functions are the recommended entry points for every compute kernel. The Spec/State/Report dataclasses are the typed inputs and outputs those entry points consume and return. :func:evaluate_merge_trigger composes the kinematic, safety, lifecycle, and recovery surfaces into one end-to-end FRC merge fire/abort/hold decision.

AERControlObservation(spike_stream, decode_window_ns, decode_strategy='rate', n_channels=None, start_ns=None) dataclass

Local upstream-pending ControlObservation adapter for AER streams.

spike_count property

Return the number of spikes inside the decode window.

window_start_ns property

Return the inclusive decode-window start timestamp.

window_stop_ns property

Return the exclusive decode-window stop timestamp.

to_features()

Return the decoded feature vector.

AERDecodedObservation(spec, features, window_start_ns, window_stop_ns, spike_count) dataclass

Decoded ControlObservation-compatible feature vector.

__post_init__()

Freeze decoded features and validate observation counters.

AERDecodeSpec(n_channels, window_ns, strategy='rate', start_ns=None) dataclass

Decode settings for AER spike streams.

__post_init__()

Validate the decode channel count, time window, and optional start.

AERSpikeEvent(address, t_ns, polarity=1) dataclass

Single address-event spike.

__post_init__()

Validate and freeze the spike event address, timestamp, and polarity.

SpikeBuffer(capacity)

Deterministic monotone AER spike ring buffer.

events property

Return buffered events in arrival order.

n_channels property

Return the minimum channel count that covers all buffered addresses.

__len__()

Return the number of buffered spike events.

push(event)

Append one monotone event, dropping the oldest event when full.

clear()

Remove all buffered events and reset timestamp state.

decode(spec)

Decode buffered events according to spec.

DataBusMock(config)

Deterministic in-memory DAQ bus mock for UDP multicast and PCIe DMA modes.

dropped_frames property

Return the number of frames overwritten by the PCIe-style ring.

bound_endpoint property

Return the validated mock endpoint, if one has been bound.

__len__()

Return the number of frames currently held in the replay ring.

bind(bind_addr)

Validate and record the mock endpoint without opening real sockets.

inject_frame(frame)

Inject one frame into the selected delivery mock.

emit_frame()

Emit the next frame in deterministic FIFO order.

emit_diagnostic_sample()

Emit the next frame as a diagnostic sample.

replay_throughput_report(frames)

Return deterministic throughput from frame timestamps.

DescriptorProfile(profile_id, sample_period_ns, channels, units, aer_addresses) dataclass

Config-driven descriptor for a vendor-style diagnostic frame.

profile_code property

Return the stable on-wire profile code.

__post_init__()

Validate the descriptor profile identifier, channel count, and addresses.

RawDaqFrame(mode, profile, sequence, t_ns, values) dataclass

Byte-stable DAQ frame carrying one ordered diagnostic value vector.

__post_init__()

Validate the raw DAQ frame metadata and finite payload values.

to_bytes()

Encode the frame into the stable MIF-018 little-endian wire format.

to_diagnostic_frame()

Return the decoded diagnostic sample in descriptor channel order.

ReplayConfig(mode, profile, ring_capacity=1024, min_replay_throughput_fps=10000.0) dataclass

Configuration for a DAQ replay bus mock.

__post_init__()

Validate replay mode, ring capacity, and throughput threshold.

ReplayThroughputReport(frame_count, first_t_ns, last_t_ns, replay_duration_s, throughput_fps, meets_baseline) dataclass

Deterministic timestamp-semantics throughput report.

DegradedSensorStream(config)

Apply deterministic noise, dropout, and jitter to diagnostic frames.

audit_log property

Return audit records from the most recent :meth:apply call.

apply(sample_stream)

Return degraded frames with deterministic per-frame audit logging.

apply_with_audit(sample_stream)

Return degraded frames and audit records together.

DiagnosticChannelCalibration(name, unit, physical_min, physical_max, clip_policy, provenance, aer_address=None) dataclass

Calibration record for one physical diagnostic channel.

Parameters are deliberately stored in physical units. The derived offset and scale properties are included in manifests so an AER ingestion chain can reproduce the exact affine mapping without inferring it from opaque data.

offset property

Physical midpoint subtracted before applying scale.

scale property

Multiplicative factor from physical units into the normalized interval.

__post_init__()

Validate channel labels, physical range, clip policy, and AER address.

normalise_value(value)

Return (normalised_value, clipped) for a single channel sample.

to_manifest_row()

Return the durable manifest row for this channel.

DiagnosticFrame(t_ns, samples) dataclass

One timestamped physical diagnostic sample frame.

__post_init__()

Validate timestamp and freeze finite diagnostic sample values.

DiagnosticNormalisationState(calibrations, *, sample_period_ns=None)

Deterministic ordered normalisation state for a diagnostic vector.

calibrations property

Ordered immutable channel calibrations.

channel_names property

Ordered channel names matching feature-vector order.

sample_period_ns property

Nominal sample period associated with the diagnostic frame.

normalise_sample(sample)

Normalise a mapping of physical channel samples into [-1, 1].

normalise_vector(values)

Normalise a positional vector in calibration order.

normalise_batch(samples)

Return a read-only (n_samples, n_channels) matrix of bounded features.

calibration_manifest()

Return the explicit calibration manifest required by MIF-016.

DropoutSpec(probability_by_channel) dataclass

Per-channel Bernoulli dropout probability.

__post_init__()

Validate dropout probabilities by channel.

JitterSpec(min_ns=10, max_ns=50, probability=1.0, signed=True) dataclass

Timestamp jitter envelope in nanoseconds.

By default the sampled jitter is signed so the degradation model covers early and late diagnostic arrivals. min_ns and max_ns describe the absolute jitter magnitude. Set signed=False only for legacy one-sided positive-jitter replay.

__post_init__()

Validate jitter bounds and application probability.

NoiseSpec(sigma_by_channel) dataclass

Per-channel additive Gaussian noise scale in physical units.

__post_init__()

Validate non-negative Gaussian-noise bounds by channel.

NormalisedDiagnosticSample(channel_names, features, clip_mask, out_of_range_channels, sample_period_ns=None) dataclass

Read-only normalised diagnostic vector plus clipping metadata.

__post_init__()

Freeze the normalised features and validate masks and channel metadata.

to_aer_features()

Return the bounded feature vector consumed by the AER front-end.

StressCampaignReport(stable, campaign_count, max_abs_phase_error_rad, max_jitter_ns, max_dropout_probability, failure_reasons) dataclass

Aggregate result for the 100-seed phase-lock regression.

StressEnvelope(max_noise_sigma_by_channel=_DEFAULT_ALLOWED_SIGMA, max_dropout_probability=0.05, min_jitter_ns=10, max_jitter_ns=50, phase_lock_tolerance_rad=0.01) dataclass

Fail-closed regression bounds for MIF-017 stress campaigns.

__post_init__()

Validate stress envelope limits used by campaign summaries.

StressInjectionConfig(seed, noise, dropout, jitter=JitterSpec()) dataclass

Complete deterministic degradation configuration.

__post_init__()

Validate deterministic stress-injection seed.

StressInjectionRecord(frame_index, source_t_ns, emitted_t_ns, jitter_ns, noisy_channels, dropped_channels) dataclass

Audit record for one degraded diagnostic frame.

StressInjectionResult(frames, records) dataclass

Degraded frames plus audit records.

EcosystemReport(generated_at_utc, code_root, siblings) dataclass

Aggregate dynamic compatibility report for MIF ecosystem consumers.

by_key()

Return sibling rows keyed by repository identifier.

require(key)

Return a sibling row and raise when the report does not contain it.

to_dict()

Return a JSON-serialisable representation.

SiblingReport(key, package, module, repo_path, role, lane, current_gate, source_version, import_version, import_status, import_detail, status, surfaces, notes) dataclass

Dynamic compatibility row for one sibling repository.

failed_surfaces property

Return required surfaces that were not found.

to_dict()

Return a JSON-serialisable representation.

SiblingSpec(key, package, module, repo_dir, role, lane, current_gate, surfaces, notes=()) dataclass

A sibling repository contract consumed by MIF.

SurfaceReport(name, status, detail) dataclass

Availability report for one sibling surface.

to_dict()

Return a JSON-serialisable representation.

SurfaceSpec(name, detail, module=None, symbols=(), file_path=None, tokens=()) dataclass

One source or import surface MIF expects from a sibling repository.

ImasInputMapping(mif_signal, mif_lane, ids_name, ids_path, direction, note) dataclass

One MIF input mapped onto an IMAS IDS path.

Parameters

mif_signal : str The MIF-consumed input (the chamber-side or prescribed sibling signal). mif_lane : str The MIF lane that consumes the signal. ids_name : str The IMAS Interface Data Structure name. ids_path : str The path within the IDS a consumer reads or publishes. direction : str consumed for an input MIF reads, published for a value MIF emits. note : str Provenance or convention note (e.g. the COCOS equilibrium convention).

TriggerEgress(timestamp, fire, veto_active) dataclass

A timestamped trigger-edge decision leaving for the coil switch.

TriggerIngress(timestamp, spike_count, confidence_q8_8, bank_ready, safety_veto) dataclass

A timestamped sensor-edge event arriving at the trigger fabric.

The evidence fields mirror the MIF-008 fabric inputs so the contract is the one decision the chamber-side lane consumes.

WhiteRabbitTimestamp(tai_seconds, nanoseconds, picoseconds=0) dataclass

A White-Rabbit TAI timestamp with sub-nanosecond resolution.

Parameters

tai_seconds : int TAI seconds since the epoch; must be non-negative. nanoseconds : int Nanoseconds within the second, in [0, 1_000_000_000). picoseconds : int Sub-nanosecond remainder, in [0, 1000); carries the White-Rabbit sub-nanosecond precision.

total_picoseconds property

Return the timestamp as a single integer picosecond count.

__post_init__()

Validate the timestamp fields without changing their precision.

picoseconds_since(earlier)

Return the signed picosecond interval from earlier to this stamp.

DopplerKuramoto(spec, phases_rad, positions_m, velocities_m_s)

Stateful RK4 integrator for the MIF-001 axial Doppler-Kuramoto carrier.

t_s property

Current simulation time in seconds.

phases_rad property

Read-only current phase vector in radians.

positions_m property

Read-only current axial positions in metres.

velocities_m_s property

Read-only constant axial velocities in metres per second.

state()

Return a read-only snapshot of the current state.

derivatives(phases_rad=None, positions_m=None, t_s=None)

Return dtheta/dt for the supplied or current phase/position state.

step(dt_s)

Advance the coupled phase/linear-position state by dt_s seconds.

copy()

Return an independent copy of the current integrator state.

DopplerKuramotoReport(time_s, phases_rad, positions_m, order_parameter, phase_lock_error_rad) dataclass

Batch simulation trace for a Doppler-Kuramoto run.

DopplerKuramotoSpec(omega_rad_s, coupling_rad_s, phase_lag_rad=0.0, doppler_strength_rad_s=0.0, velocity_epsilon_m_s=1e-09, distance_scale_m=1.0, omega_rate_rad_s2=None) dataclass

Immutable Doppler-Kuramoto parameter set.

Attributes

omega_rad_s: Natural angular frequencies in radians per second. coupling_rad_s: Square off-diagonal coupling matrix. Entry K[i, j] weights the phase pull from oscillator j onto oscillator i before distance decay. omega_rate_rad_s2: Optional affine natural-frequency rates in radians per second squared. None is normalised to a zero vector. phase_lag_rad: Sakaguchi-style phase lag :math:\alpha in radians. doppler_strength_rad_s: Scale factor :math:\gamma applied to each off-diagonal, pair-normalised relative-velocity Doppler correction. velocity_epsilon_m_s: Positive denominator guard for stationary or near-stationary channels. distance_scale_m: Positive axial length scale :math:L_z used to make distance decay dimensionless.

n_oscillators property

Number of coupled oscillators in the carrier.

__post_init__()

Validate oscillator arrays and freeze the Doppler-Kuramoto specification.

omega_at(t_s=0.0)

Return natural angular frequencies at simulation time t_s.

DopplerKuramotoState(t_s, phases_rad, positions_m, velocities_m_s, order_parameter, phase_lock_error_rad) dataclass

Single state snapshot from the Doppler-Kuramoto carrier.

KinematicSafetyCertificate(passed, samples, tolerance_m, contraction, disturbance_ratio, budget_margin, max_abs_separation_m, initial_margin_m, minimum_step_slack_m, max_step_violation_m, first_violation_index) dataclass

Trace-level certificate for the sampled Lean safety assumptions.

first_violation_index uses zero-based sample indices across Python, Rust/PyO3, and Julia surfaces.

KinematicSafetySpec(tolerance_m=KINEMATIC_SAFETY_TOLERANCE_M, contraction=0.9, disturbance_ratio=0.1, numerical_tolerance_m=1e-12) dataclass

Sampled safety envelope parameters matching the Lean MIF-011 theorem.

budget_margin property

Return 1 - contraction - disturbance_ratio.

__post_init__()

Validate sampled safety-envelope parameters against the Lean budget.

MergeWindowFeatureBoundaryError

Bases: ValueError

Raised when a feature mapping crosses the lock-window boundary.

Either an offered key is not in :data:MERGE_WINDOW_FEATURE_KEYS (an out-of-boundary ingestion — the boundary-creep the predictor contract forbids), or a required key is missing (an underspecified feature vector). Both are fail-closed: the predictor may never run on an unvalidated mapping.

MergeWindowFeatureVector(phase_lock_error_rad, reference_error_m, separation_m, streak, order_parameter) dataclass

A validated lock-window feature vector — the predictor's only admissible input.

The fields are exactly the keys of :data:MERGE_WINDOW_FEATURE_KEYS. Construct it from real monitor output with :func:merge_window_feature_vector; the frozen, slotted shape means no out-of-boundary attribute can be smuggled in after the fact.

to_mapping()

Return the feature vector as a plain {key: value} mapping.

The streak count is widened to float so the whole vector is numerically uniform for a downstream model, while the dataclass keeps its integer field.

MergeWindowMonitor(spec)

Stateful spatial + phase merge-window monitor with monotone sample time.

reset()

Clear streak and first-lock state.

evaluate(phases_rad, positions_m, t_s=None)

Evaluate one phase/position sample and update the consecutive streak.

MergeWindowPrediction(score, lock_probability, conformal_lower_probability, conformal_upper_probability, decision_threshold, safety_passed, veto_permit, boundary_validated, advisory_fire_permitted, reason, provenance) dataclass

Veto-subordinate advisory prediction for one lock-window feature vector.

The probability interval is clipped to [0, 1]. advisory_fire_permitted is true only when the kinematic safety certificate passed, the veto gate permitted fire, and the conformal lower probability meets the configured threshold.

MergeWindowPredictorWeights(intercept, phase_lock_error_weight, reference_error_weight, separation_weight, streak_weight, order_parameter_weight, conformal_radius, decision_threshold, provenance) dataclass

Runtime grey-box weights calibrated on a verified FUSION surrogate seam.

Parameters

intercept: Logistic-model intercept. phase_lock_error_weight: Weight for phase_lock_error_rad from the lock-window feature vector. reference_error_weight: Weight for reference_error_m from the lock-window feature vector. separation_weight: Weight for separation_m from the lock-window feature vector. streak_weight: Weight for streak from the lock-window feature vector. order_parameter_weight: Weight for order_parameter from the lock-window feature vector. conformal_radius: Additive probability radius for conformal prediction intervals. decision_threshold: Probability threshold the conformal lower bound must meet before the advisory can accept a window. provenance: Runtime calibration provenance. It must start with verified-surrogate: so analytic-only weights cannot satisfy ADR 0010.

__post_init__()

Validate numeric weights and verified-surrogate calibration provenance.

MergeWindowSample(t_s, phase_lock_error_rad, reference_error_m, separation_m, candidate_lock, lock_achieved, streak) dataclass

Single merge-window evaluation sample.

MergeWindowSpec(phase_tolerance_rad=0.01, spatial_tolerance_m=0.002, consecutive_samples=3, reference_point_m=0.0) dataclass

Immutable merge-window tolerances.

__post_init__()

Validate merge-window tolerances and required consecutive samples.

MergeWindowTrace(lock_achieved, first_lock_time_s, samples) dataclass

Trace-level merge-window report.

MovingFrameUPDE(spec, phases_rad, positions_m, velocities_m_s)

Stateful fixed-step Dormand-Prince RK45 integrator for MIF-002.

state()

Return a read-only snapshot of the current state.

derivatives(phases_rad=None, positions_m=None, t_s=None)

Return the combined [dtheta/dt, dz/dt] derivative vector.

step(dt_s)

Advance the combined phase/position state by dt_s seconds.

time_to_reference_s()

Return non-negative time-to-reference estimates for each oscillator.

collision_imminent(eps_m=0.002)

Return whether all channels are inside eps_m of the reference point.

copy()

Return an independent copy of the current integrator state.

MovingFrameUPDEReport(time_s, phases_rad, positions_m, separation_m, reference_error_m, order_parameter, phase_lock_error_rad, local_error_estimate) dataclass

Batch simulation trace for a moving-frame UPDE run.

MovingFrameUPDESpec(omega_rad_s, coupling_rad_s, phase_lag_rad=0.0, doppler_strength_rad_s=0.0, velocity_epsilon_m_s=1e-09, distance_scale_m=1.0, reference_point_m=0.0, omega_rate_rad_s2=None) dataclass

Immutable moving-frame UPDE parameter set.

n_oscillators property

Number of moving oscillators.

phase_spec property

Underlying Doppler-Kuramoto phase-law spec.

__post_init__()

Build and freeze the Doppler phase spec used by the moving-frame solver.

MovingFrameUPDEState(t_s, phases_rad, positions_m, velocities_m_s, reference_point_m, separation_m, reference_error_m, order_parameter, phase_lock_error_rad, local_error_estimate) dataclass

Single moving-frame UPDE state snapshot.

BankTelemetry(voltage_V, voltage_max_V, energy_J) dataclass

Capacitor-bank telemetry consumed by lifecycle transition guards.

voltage_fraction property

Return bank voltage as a fraction of the declared maximum.

__post_init__()

Validate bank telemetry and freeze the derived charge fraction.

CapacitorBank(spec, initial_voltage_V=0.0)

Series RLC capacitor bank with Crank-Nicolson numerical integration.

The bank tracks the state pair (v_C, i_L). The free-response dynamics obey the linear ODE :math:\dot y = A y with :math:A = \begin{pmatrix} 0 & -1/C \\ 1/L & -R/L \end{pmatrix}. :meth:step advances the state via the unconditionally stable Crank-Nicolson scheme

.. math::

\left(I - \frac{\Delta t}{2} A\right) y_{n+1}
= \left(I + \frac{\Delta t}{2} A\right) y_n.
Parameters

spec : CapacitorBankSpec Physical specification of the bank. initial_voltage_V : float, default 0.0 Initial bank voltage. Must lie in [0, spec.voltage_max_V].

spec property

Underlying immutable bank specification.

state property

Current observable state.

natural_peak_current_a property

Return the instantaneous short-circuit current bound.

Returns

float Conservative natural-response bound |v_C| / sqrt(L / C) in amperes for an initially charged, zero-current series LC bank.

reset(voltage_V=0.0)

Reset the bank to voltage_V with zero current and t = 0.

step(dt, external_load_current_A=0.0)

Advance the bank state by dt using Crank-Nicolson.

Parameters

dt : float Time step in seconds. Must be strictly positive. external_load_current_A : float, default 0.0 Instantaneous current drawn by an external load attached to the capacitor, in amperes. Zero recovers the natural response.

Raises

ValueError If dt is not strictly positive.

discharge(pulse, dt, n_steps)

Drive the bank with a prescribed load-current waveform.

Steps n_steps times with the load current sampled from the pulse waveform at the centre of each interval, tracks peak voltage and peak current observed during the run, and returns an :class:EnergyReport summarising the energy budget.

Energy bookkeeping always satisfies the sampled invariant energy_delivered + energy_remaining == initial_total_energy where total energy is :math:\tfrac12 C v_C^2 + \tfrac12 L i_L^2. The delivered amount is the electromagnetic energy removed from storage by the external load and the series resistance during the sampled pulse.

Parameters

pulse : PulseSpec Prescribed load-current waveform descriptor. dt : float Integration step in seconds; must be strictly positive. n_steps : int Number of integration steps; must be strictly positive.

Raises

ValueError If dt or n_steps is not strictly positive.

feasibility(pulse)

Cheap admissibility check for a candidate pulse against bank state.

Returns a tuple (feasible, reason). The check is conservative; a pulse failing this check definitely cannot run, but a passing pulse may still under-deliver under detailed simulation.

Two guards are applied, in order:

  1. The requested peak current must not exceed the natural short-circuit peak :math:V_0 / Z_0 (with :math:Z_0 = \sqrt{L/C}), for non-zero initial voltage. Inductive storage :math:\tfrac{1}{2} L i^2 is recoverable (returned by the coil at pulse end), so it is not counted against the available energy.
  2. The bank's stored energy must cover the resistive dissipation :math:R \, \langle i^2 \rangle \, \tau — the irreversible Joule heating in the series resistance.

recharge_status(t)

Project bank state after t seconds of linear-power recharge.

The bank is modelled as accepting constant electrical power recharge_power_kW (clipped at voltage_max_V); the energy balance gives :math:V(t) = \sqrt{V_0^2 + 2 P_\mathrm{recharge} t / C}.

Returns a dictionary with keys target_voltage_V, projected_voltage_V, and time_to_full_s. When recharge_power_kW is zero the projected voltage stays at the current value and time_to_full_s is +inf.

Raises

ValueError If t is negative.

CapacitorBankSpec(capacitance_F, inductance_H, series_resistance_ohm, voltage_max_V, recharge_power_kW, safety_envelope=dict()) dataclass

Immutable physical and operational specification of a capacitor bank.

Attributes

capacitance_F : float Total bank capacitance in farads. Must be strictly positive. inductance_H : float Loop inductance (bank plus leads) in henries. Must be strictly positive. series_resistance_ohm : float Total series resistance (ESR plus lead resistance) in ohms. Must be non-negative. voltage_max_V : float Hard upper bound on the bank voltage. Strictly positive. recharge_power_kW : float Linear recharging-power budget in kilowatts. Non-negative. safety_envelope : dict[str, float] Optional named operational margins consumed by external guards.

damping_factor property

Damping factor :math:\alpha = R / (2 L) (rad s⁻¹).

resonant_frequency property

Undamped resonant frequency :math:\omega_0 = 1 / \sqrt{L C} (rad s⁻¹).

critical_resistance property

Critical-damping resistance :math:R_\mathrm{crit} = 2 \sqrt{L / C} (ohm).

regime property

Damping regime implied by series_resistance_ohm vs critical_resistance.

__post_init__()

Validate capacitor-bank circuit constants and safety envelope values.

CapacitorBankState(t, voltage_V, energy_J, capacitor_energy_J, inductor_energy_J, current_A, di_dt_A_s, discharge_active, recharge_active) dataclass

Immutable observable state of the bank at time t.

EnergyReport(energy_delivered_J, energy_remaining_J, peak_voltage_V, peak_current_A, discharge_duration_s, rlc_regime) dataclass

Summary of a completed discharge sequence.

MergerMarking(tokens, total_tokens) dataclass

Token marking for the one-safe merger net.

max_tokens_per_place property

Return the maximum token count held by any place.

MergerObservation(separation_m, relative_velocity_m_s, phase_lock_error_rad, reconnection_flux_norm, density_asymmetry, tilt_growth_rate_s) dataclass

Single sampled observation driving the merger Petri-net guards.

__post_init__()

Validate observed plasmoid-merger state scalars.

MergerPlace

Bases: StrEnum

Places in the MIF FRC plasmoid-merger Petri net.

MergerStep(tick, place, transition, fired, reason, dwell_ticks, marking) dataclass

Result of evaluating one sampled observation.

MergerTransition

Bases: StrEnum

Transitions in the MIF FRC plasmoid-merger Petri net.

MergerTransitionRecord(tick, transition, from_place, to_place, reason) dataclass

Audit record for a fired merger transition.

MergerVerificationReport(passed, trials, steps_per_trial, failures, terminal_counts, max_tokens_per_place) dataclass

Boundedness or liveness verification summary.

PlasmaState(coil_current_A, temperature_eV, phase_lock_error_rad, reference_error_m, fusion_power_W, radial_velocity_m_s) dataclass

Plasma telemetry consumed by lifecycle transition guards.

__post_init__()

Validate plasma-state telemetry used by shot scheduling.

PlasmoidMergerPetriNet(spec, seed=None)

Stateful one-safe stochastic Petri net for MIF FRC merger control.

audit_log property

Return immutable fired-transition audit entries.

reset(seed=None)

Reset to the initial approach marking.

copy()

Return a copy with identical state and an independently seeded RNG.

marking()

Return the current one-safe marking.

enabled_transition(observation)

Return the transition currently enabled by observation.

step(observation)

Evaluate one sampled observation and fire at most one transition.

PlasmoidMergerSpec(contact_separation_m=0.002, min_closing_speed_m_s=300000.0, reconnection_flux_min=0.72, coalescence_density_asymmetry_max=0.12, phase_lock_tolerance_rad=0.01, max_tilt_growth_rate_s=50000.0, contact_delay_ticks=1, reconnection_delay_ticks=2, coalescence_delay_ticks=2, phase_lock_delay_ticks=3, firing_probability=1.0, abort_density_asymmetry_max=0.35) dataclass

Guard thresholds and stochastic firing policy for MIF-012.

__post_init__()

Validate Petri-net thresholds and abort limits.

PulsedShotFSM(spec)

Eight-state pulsed-shot lifecycle finite-state machine.

audit_log property

Return immutable transition audit entries.

reset()

Return to idle and clear timestamp and audit state.

transition_to(next_state, t_s, reason)

Perform a validated manual adjacent transition.

step(t_s, plasma, bank)

Evaluate lifecycle guards at t_s and emit the active-state command.

audit_log_jsonl()

Return the transition audit log as newline-delimited JSON.

PulsedShotSpec(min_precharge_energy_J, ramp_current_A, phase_tolerance_rad, spatial_tolerance_m, burn_temperature_eV, min_fusion_power_W, expansion_velocity_m_s, dump_energy_floor_J, recharge_voltage_fraction, cooldown_temperature_eV, cooldown_current_A, min_burn_duration_s=0.0) dataclass

Guard thresholds for the pulsed-shot lifecycle.

__post_init__()

Validate pulsed-shot FSM threshold parameters.

PulseSpec(peak_current_A, duration_s, waveform='half_sine') dataclass

Specification of a requested discharge pulse.

__post_init__()

Validate compression-pulse current, duration, and waveform label.

RLCRegime

Bases: StrEnum

Classification of the series RLC natural response.

SchedulerAction

Bases: StrEnum

Command action emitted for the active lifecycle state.

SchedulerCommand(t_s, state, action, reason, transition, dwell_s) dataclass

Command emitted by one lifecycle FSM step.

ShotState

Bases: StrEnum

Canonical pulsed-shot lifecycle states.

TransitionRecord(t_s, from_state, to_state, reason) dataclass

Single lifecycle transition audit entry.

to_json()

Return the stable JSON-serialisable audit representation.

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.

MergeTriggerOutcome

Bases: StrEnum

Decision emitted by the merge-trigger pipeline.

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.

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.

FaradayRecoveryReport(time_s, flux_Wb, flux_rate_Wb_s, back_emf_V, recovered_power_W, recovered_energy_J, peak_abs_back_emf_V, peak_recovered_power_W) dataclass

Waveform-level Faraday recovery observables.

FaradayRecoverySpec(turns, load_resistance_ohm, coupling_efficiency=1.0) dataclass

Immutable recovery-coil and load specification.

Attributes

turns : float Positive effective turn count of the recovery coil. Fractional values are accepted to represent winding/coupling calibration. load_resistance_ohm : float Positive ohmic load presented to the induced EMF. coupling_efficiency : float Dimensionless power-transfer efficiency in [0, 1].

__post_init__()

Validate coil turns, load resistance, and coupling efficiency.

FaradayRecoveryState(radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s, flux_Wb, flux_rate_Wb_s, back_emf_V, recovered_power_W) dataclass

Pointwise Faraday recovery observables.

FusionFRCContractReport(surfaces) dataclass

Aggregate MIF-side readiness report for the FUSION FRC contract.

ready_for_mif_integration property

Return whether every required public symbol is present.

ready_for_full_evidence property

Return whether public symbols are present without blocked evidence claims.

missing_required_symbols property

Return missing symbols as FUS-C.X:symbol entries.

blocked_claim_boundaries property

Return claim-boundary statuses that still explicitly block full evidence.

FusionFRCSurface(module_id, name, required_symbols, claim_status_functions=()) dataclass

Required FUSION-owned FRC surface consumed by MIF.

FusionFRCSurfaceReport(module_id, name, present, missing_symbols, claim_statuses) dataclass

Availability and claim-boundary report for one FUSION surface.

decode_spike_features(buffer, spec)

Decode buffer and return only the feature vector.

decode_spike_observation(buffer, spec)

Decode buffer into a ControlObservation-compatible report.

dispatched_aer_spike_buffer(capacity)

Return an AER spike buffer backed by the fastest available backend.

dispatched_decode_spike_features(buffer, spec)

Decode AER features through the fastest available backend for the strategy.

decode_daq_frame(blob, profile=None)

Decode and validate a DAQ frame from the stable byte contract.

dispatched_data_bus_mock(config)

Return a DAQ bus mock backed by the fastest available backend.

encode_daq_frame(frame)

Encode a raw DAQ frame into the stable little-endian byte contract.

helion_descriptor_profile()

Return the Helion-style MIF-018 descriptor profile.

tae_descriptor_profile()

Return the TAE-style MIF-018 descriptor profile.

dispatched_degraded_sensor_stream(config)

Return a stress injector backed by the fastest available backend.

dispatched_normalisation_state(calibrations, *, sample_period_ns=None)

Return a diagnostic normalisation state backed by the fastest available backend.

evaluate_phase_lock_stability_campaigns(config, envelope=None, *, campaign_count=100, frames_per_campaign=32, dt_ns=128)

Run the MIF-017 phase-lock invariant over at least 100 seeded campaigns.

fit_diagnostic_calibrations(observations, *, units, provenance, clip_policy='clip', aer_addresses=None)

Fit min/max calibrations from observed physical samples.

Channel order follows the order of units. Every observation must contain every declared channel, and each channel must span a non-zero physical range.

validate_stress_config(config, envelope)

Fail closed when stress settings exceed documented regression bounds.

compatibility_report_json(report)

Return deterministic JSON for generated compatibility artifacts.

default_code_root()

Return the sibling repository root used by the live compatibility scan.

generate_ecosystem_report(code_root=None, *, generated_at_utc=None)

Inspect sibling source trees and optional runtime imports.

render_compatibility_matrix(report)

Render the dynamic ecosystem report as Markdown.

egress_latency_ps(ingress, egress)

Return the sensor-edge to trigger-edge latency in picoseconds.

Raises ValueError if the egress is not at or after the ingress; a trigger cannot precede the evidence that caused it.

epics_channel(signal)

Return the EPICS process-variable name for a trigger-lane signal.

epics_channels()

Return every trigger-lane signal mapped to its EPICS process-variable name.

extract_mif_inputs(imas_payload, *, require=True)

Read MIF's consumed inputs out of an IMAS-path-keyed payload.

imas_payload maps IMAS IDS paths (as in :data:MIF_IMAS_INPUT_MAP) to values, as a consumer reading from the ITER IMAS data model would supply them. Returns {mif_signal: value} for every mapping whose direction is consumed. With require (the default), a missing consumed path raises KeyError; otherwise it is skipped. This is the active consumer of the mapping contract — the inverse pairs with mapping_for(signal).ids_path for a round-trip.

ids_names(mappings=None)

Return the sorted unique IMAS IDS names referenced by the mappings.

mapping_for(mif_signal)

Return the IMAS mapping for mif_signal.

Raises KeyError if the signal is not mapped.

certify_positions_sampled_kinematic_safety(positions_m, spec=None)

Certify a two-dimensional sampled position trace by max-min separation.

certify_sampled_kinematic_safety(separation_m, spec=None)

Certify a sampled axial-separation trace against the MIF-011 envelope.

dispatched_doppler_kuramoto(spec, phases_rad, positions_m, velocities_m_s)

Return a Doppler-Kuramoto engine backed by the fastest available backend.

dispatched_merge_window_monitor(spec)

Return a merge-window monitor backed by the fastest available backend.

dispatched_moving_frame_upde(spec, phases_rad, positions_m, velocities_m_s)

Return a moving-frame UPDE engine backed by the fastest available backend.

dispatched_sampled_kinematic_safety_certificate(separation_m, spec=None)

Return a sampled safety certificate from the fastest available backend.

doppler_derivatives(spec, phases_rad, positions_m, velocities_m_s, t_s=0.0)

Return the MIF-001 pointwise phase derivative vector.

evaluate_doppler_kuramoto(spec, phases_rad, positions_m, velocities_m_s, dt_s, steps)

Run steps RK4 updates and return the full phase/position trace.

evaluate_merge_window_trace(spec, time_s, phases_rad, positions_m)

Evaluate a full merge-window trace.

evaluate_moving_frame_upde(spec, phases_rad, positions_m, velocities_m_s, dt_s, steps)

Run steps RK45 updates and return the full moving-frame trace.

is_within_merge_window_boundary(features)

Return whether features is exactly the admissible lock-window set.

A total, non-raising counterpart to :func:validate_merge_window_features for call sites that branch on admissibility rather than enforce it.

load_merge_window_predictor_weights(path)

Load runtime predictor weights from a JSON file.

Parameters

path: JSON file containing the fields of :class:MergeWindowPredictorWeights.

Returns

MergeWindowPredictorWeights Validated weights with verified-surrogate provenance.

Raises

ValueError If the JSON payload is not an object or any field is invalid.

merge_window_feature_vector(sample, state)

Extract the boundary-safe feature vector from real monitor output.

This is the only sanctioned construction path: it reads the lock-window observables (alignment, reference error, separation, streak) off the sample :class:~scpn_mif_core.kinematic.merge_window.MergeWindowSample and the phase coherence (order parameter) off the state :class:~scpn_mif_core.kinematic.doppler_kuramoto.DopplerKuramotoState at the same instant, so the returned vector is lock-window by construction and never touches sibling physics.

moving_frame_derivatives(spec, phases_rad, positions_m, velocities_m_s, t_s=0.0)

Return the combined [dtheta/dt, dz/dt] derivative vector.

order_parameter(phases_rad)

Return the Kuramoto order parameter |mean(exp(i theta))|.

phase_lock_error(phases_rad)

Return the maximum circular pairwise phase separation in radians.

predict_merge_window(features, weights, safety_certificate, *, veto_permit)

Predict whether a lock window is admissible inside verified gates.

Parameters

features: The closed ADR 0010 lock-window feature vector, either as the dataclass returned by :func:merge_window_feature_vector or as an exact mapping with the same keys. weights: Runtime grey-box weights loaded from verified-surrogate provenance. safety_certificate: Existing MIF-011 sampled kinematic safety certificate. A failed certificate always blocks the advisory regardless of model score. veto_permit: Existing hardware veto/fast-veto decision. False always blocks the advisory regardless of model score.

Returns

MergeWindowPrediction Probability, conformal interval, and the final veto-subordinate advisory.

validate_merge_window_features(features)

Fail closed unless features is exactly the lock-window feature set.

features is the candidate mapping destined for the predictor. This raises :class:MergeWindowFeatureBoundaryError when any key lies outside :data:MERGE_WINDOW_FEATURE_KEYS (boundary creep) and, separately, when any required key is absent (an underspecified vector); the out-of-boundary keys are reported before a missing key so the violation is actionable.

analytical_current_critically_damped(spec, t, v0)

Critically damped current closed form: :math:i(t) = (V_0 / L) \, t \, e^{-\alpha t}.

analytical_current_overdamped(spec, t, v0)

Overdamped current closed form.

:math:i(t) = \dfrac{V_0}{L (s_1 - s_2)} \left( e^{s_1 t} - e^{s_2 t} \right).

analytical_current_underdamped(spec, t, v0)

Underdamped current closed form.

:math:i(t) = \dfrac{V_0}{\omega_d L} \, e^{-\alpha t} \sin(\omega_d t).

analytical_voltage_critically_damped(spec, t, v0)

Critically damped voltage closed form: :math:v_C(t) = V_0 \, e^{-\alpha t} (1 + \alpha t).

analytical_voltage_overdamped(spec, t, v0)

Overdamped voltage closed form.

With :math:\beta = \sqrt{\alpha^2 - \omega_0^2} and :math:s_{1,2} = -\alpha \pm \beta,

:math:v_C(t) = V_0 \, \dfrac{s_1 e^{s_2 t} - s_2 e^{s_1 t}}{s_1 - s_2}.

analytical_voltage_underdamped(spec, t, v0)

Underdamped voltage closed form.

:math:v_C(t) = V_0 \, e^{-\alpha t} \left[ \cos(\omega_d t) + (\alpha / \omega_d) \sin(\omega_d t) \right], valid when spec.regime is RLCRegime.UNDERDAMPED.

build_control_petri_net(spec, net_factory=None)

Build the pinned SCPN-CONTROL StochasticPetriNet shape for MIF-012.

dispatched_capacitor_bank(spec, initial_voltage_V=0.0)

Return a :class:CapacitorBank instance backed by the fastest available backend.

Consults :file:bench/dispatch.toml via :func:scpn_mif_core._dispatch.preferred_backend and instantiates the Rust-backed adapter when the dispatch table prefers it and the extension is importable. Falls back to the pure Python class otherwise. The returned instance is API-compatible with :class:CapacitorBank so downstream code stays backend-agnostic.

dispatched_plasmoid_merger_petri_net(spec, seed=None)

Return a plasmoid-merger Petri net backed by the fastest available backend.

dispatched_pulsed_shot_fsm(spec)

Return a pulsed-shot FSM backed by the fastest available backend.

free_response(spec, t, v0)

Return (v_C(t), i(t)) of the series RLC natural response at time t.

Dispatches to the analytical formulas for the regime implied by spec.regime. The initial conditions are v_C(0) = v0 and i(0) = 0.

Raises

ValueError If t is negative.

verify_merger_boundedness(spec=None, *, trials=100, steps_per_trial=500, seed=0)

Run the requested stochastic boundedness campaign.

verify_merger_liveness(spec=None, *, trials=1000, steps_per_trial=200, seed=0)

Run the requested liveness campaign against nominal merger stimuli.

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.

dispatched_evaluate_faraday_recovery(spec, time_s, radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s)

Return a waveform report from the fastest available measured backend.

dispatched_faraday_back_emf(radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s, turns)

Return Faraday back-EMF from the fastest available measured backend.

evaluate_faraday_recovery(spec, time_s, radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s)

Evaluate a full Faraday recovery waveform and integrate recovered energy.

The velocity and field-rate arrays are explicit inputs so the waveform path uses the same exact product-rule carrier as the scalar path; no hidden finite-difference derivative is introduced here.

evaluate_faraday_state(spec, radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s)

Evaluate pointwise flux, EMF, and recovered power.

faraday_back_emf(radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s, turns)

Return induced back-EMF -turns * dPhi/dt in volts.

flux_rate(radius_m, radial_velocity_m_s, magnetic_field_T, magnetic_field_rate_T_s)

Return d(B_ext * pi * R_s**2) / dt in webers per second.

inspect_fusion_frc_contract(fusion_core=None)

Inspect whether the FUSION FRC surfaces needed by MIF are available.

load_fusion_core()

Import the optional scpn_fusion.core public surface.

magnetic_flux(radius_m, magnetic_field_T)

Return external magnetic flux B_ext * pi * R_s**2 in webers.

recovered_power(spec, back_emf_V)

Return instantaneous load power from a Thevenin EMF source.

Rust workspace

Crate Purpose
mif-types Shared types: FRC equilibrium, capacitor bank, AER spikes, pulse identifiers
mif-core Core orchestration and shared algorithms
mif-kinematic Doppler-corrected Kuramoto, moving-frame UPDE, merge-window monitor
mif-lifecycle Pulsed-shot FSM and capacitor-bank state model
mif-aer AER ingestion ring buffer and decode strategies
mif-diagnostics Dirty diagnostic calibration and normalisation kernels
mif-fpga FPGA-side glue and SystemVerilog IR helpers
mif-ffi PyO3 bridge

Implemented pre-alpha API pages:

  • Doppler-Kuramoto — MIF-001, pair-normalised Doppler-corrected axial Kuramoto carrier with Python, Rust, and Julia surfaces.
  • Moving-frame UPDE — MIF-002, chamber-fixed absolute-position UPDE carrier with Python, Rust, and Julia surfaces and circular RK45 phase-error bookkeeping.
  • Merge-window monitor — MIF-003, spatial + phase lock predicate with Python and Rust surfaces and strictly increasing sample-time validation.
  • Pulsed-shot FSM — MIF-004, eight-state lifecycle scheduler with Python, Rust, and Lean surfaces.
  • Pulsed-shot proof — MIF-004, Lean 4 adjacency determinism and minimal eight-step lifecycle proof.
  • Capacitor bank — MIF-005, series RLC capacitor-bank model with total electromagnetic energy bookkeeping across Python, Rust, Julia, and Lean formal surfaces.
  • Capacitor-bank proof — MIF-005, Lean 4 stored-energy and recharge-energy sign contracts.
  • AER spike-buffer decoder — MIF-006, AER ingress adapter with Python, Rust, PyO3 parity, and benchmarked dispatch.
  • Diagnostic normalisation — MIF-016, calibration-manifested dirty diagnostic scaling with Python, Rust, and Julia surfaces.
  • Diagnostic stress injection — MIF-017, deterministic synthetic noise, dropout, and signed jitter hardening with Python, Rust, and Julia surfaces.
  • DAQ bus mock — MIF-018, byte-stable UDP multicast and PCIe DMA ring replay with Python, Rust, and Go surfaces.
  • Plasmoid-merger Petri net — MIF-012, one-safe stochastic Petri-net FSM with Python, Rust, and Lean formal surfaces.
  • Plasmoid-merger Petri-net proof — MIF-012, Lean 4 one-safety and nominal reachability skeleton.
  • Faraday recovery — MIF-009, exact Faraday-law carrier with Python, Rust, Julia, and Lean formal surfaces.
  • FUSION FRC contract adapter — consumer contract for FUSION-owned FRC equilibrium, Hall/flux, compression, MRTI, tilt, and compression-coupled Faraday surfaces.
  • Faraday recovery proof — MIF-009, Lean 4 energy-bookkeeping proof for the EMF and recovered-energy sign contracts.
  • Kinematic safety — PHA-C.6/MIF-011, Lean 4 sampled invariant template, 2 mm axial merge-window instantiation, and runtime proof-assumption certificate.
  • ADC-to-spike quantiser — MIF-007, B-dot ADC to Q8.8 AER spike-rate bridge with Python and SystemVerilog surfaces, cycle-level valid/ready reference, and Verilator cosimulation.