Time-Domain System Equivalent logoTime-Domain System EquivalentLinear dynamics, solved faster.Discuss an evaluation
SDK Documentation

Advanced Runtime Integration

Variable time-step behavior and integration constraints.

Audience: Integration engineers embedding TDSE into simulators with adaptive or multi-rate time-stepping (SPICE-family, PSCAD/EMTP, Keysight ADS, etc.).

Use this chapter when your simulator does not step at exactly the same interval used to build the pack. It explains how runtime dt relates to build-time model_dt, what accuracy changes when they differ, and which integration patterns are usually safe.

This chapter starts with variable time-step integration, then continues into runtime concurrency, scaling, and multi-model deployment patterns in the sections that follow.

Use it only after the fixed-step step loop is already understood. For a first minimal integration, keep dt_runtime = model_dt and return here only when the host truly needs adaptive or multi-rate stepping.

The three most common host cases are:

Host caseRecommended first policy
fixed-step simulatorkeep dt_runtime = model_dt
adaptive simulatorstart with clamped adaptive dt, then measure interpolation error
multi-rate orchestrationuse multiple model handles, one time base per handle

Core Semantics

The impulse-response tensor h[k] (shape [nh, nq, np]) is sampled at build time with a fixed step size model_dt:

tau_k = k * model_dt,   k = 0, 1, ..., nh - 1

model_dt is an intrinsic model property, queryable via tdse_model_info_t.dt.

The dt parameter passed to tdse_step_begin(model, t, dt) is the simulator's current physical time span for this step. It does not need to equal model_dt. The runtime convolution engine bridges the two automatically.

Two Internal Paths

The runtime selects one of two paths based on the time-line history.

Uniform Fast Path

Triggered when all of these conditions are satisfied simultaneously:

  1. The committed history timeline is monotonically increasing and uniform, with step size equal to model_dt (relative tolerance 1e-9, absolute 1e-12).
  2. The current step time t minus the latest committed time t_newest equals model_dt (same tolerance).

Under this path:

  • History terms are read directly from the ring buffer by tap index, with no interpolation.
  • This is the most accurate and fastest path, equivalent to fixed-step convolution.

Time-Driven Interpolation Fallback

Entered whenever any trigger condition fails (including but not limited to: dt != model_dt, dt varying between steps, a large time-step jump, or initial conditions where the accepted queue has not yet been uniformized).

For each delayed tap k >= 1:

sample_t = t - tau_k = t - k * model_dt

The runtime performs linear interpolation on the committed primary input timeline to obtain v(sample_t), then weights and accumulates with h[k].

  • Boundary semantics: when sample_t precedes the earliest retained committed time, that tap's contribution is treated as zero. This is zero extrapolation at the retained-history boundary, not evidence that the physical system was at rest before time zero.
  • Interpolation order: first-order (linear). There is no zero-order hold or higher-order interpolation path.

Accuracy Impact

For a sufficiently smooth accepted primary signal, linear interpolation has a second-order local approximation error. The resulting history error also depends on the tap values, retained history, and host coupling; it is not a universal bound:

err(hr) = O(dt_runtime^2 * sup_t |d^2 v / dt^2|)

where v is the committed primary input sequence. Practical guidance:

ScenarioStarting sweep for dt_runtime / model_dtNotes
Smooth input (AC steady-state, low-freq transient)0.5 -- 10Large steps only lose linear interpolation accuracy in history
General transient (step, pulse)0.5 -- 2Excessive ratio causes visible "smearing" near step edges
Steep transient (switching, surge, impulse)0.5 -- 1Recommend dt_runtime ~ model_dt

Key numerical conclusions:

  • The instantaneous path (tdse_step_op, direct response in tdse_step_commit) is driven by h[0] and does not interpolate across the runtime time grid.
  • The IR term (tdse_step_ir) queries the pack's internal sampling table by absolute time t; dt_runtime affects only the time quantization.
  • Only the history term hr accumulates linear interpolation error as dt_runtime / model_dt deviates from 1.

Stability

Variable time-stepping does not rewrite the pack coefficients, but it changes the history approximation presented to the host solver. TDSE therefore makes no general stability or energy-conservation guarantee for an arbitrary variable-step host coupling. Extreme dt jumps can amplify interpolation error; validate the coupled simulation on representative transients and use the runtime metrics below as diagnostics rather than as a proof of stability.

Monitoring

When exploring aggressive dt strategies, poll runtime guard metrics via tdse_ext_context_get_runtime_guard_metrics() on the model's extension context:

MetricMeaningWatch For
max_abs_g0max amplitude of h[0] entries this stepmodel-dependent; use as trend
pivot_minminimum pivotsignificant drop means op near-singular
pivot_ratiocurrent pivot_min vs baselinesustained < 0.1 warrants investigation
growth_factorinter-step `hr

Multi-Rate Models

TDSE multi-rate at the runtime level is achieved by running multiple model handles concurrently, not through internal multi-clock support:

tdse_model_t* fast_model;  /* model_dt = 1 ns */
tdse_model_t* slow_model;  /* model_dt = 10 ns */

tdse_model_create(fast_pack, fast_len, NULL, &diag, &fast_model);
tdse_model_create(slow_pack, slow_len, NULL, &diag, &slow_model);

for (step = 0; step < N; ++step) {
    /* fast model: step every 1 ns */
    tdse_step_begin(fast_model, t_fast, 1e-9);
    /* ... */ tdse_step_commit(fast_model, primary_fast, fast_np);

    /* slow model: step every 10 ns */
    if (step % 10 == 0) {
        tdse_step_begin(slow_model, t_slow, 10e-9);
        /* ... */ tdse_step_commit(slow_model, primary_slow, slow_np);
    }
}

Each handle maintains its own history ring buffer independently. Concurrency rules still apply: no concurrent API calls on the same handle; multiple independent handles may run in parallel on different threads.

Use these in order. Do not jump to adaptive or multi-rate operation before the fixed-step path is already validated.

Fixed dt (simple SPICE integration)

Always use dt_runtime = model_dt in the simulator main loop:

const double model_dt = info.dt;
for (...) {
    tdse_step_begin(model, t, model_dt);
    /* op / hr / ir */
    tdse_step_commit(model, primary, np);
    t += model_dt;
}

Once the committed timeline is aligned and uniform, this uses the uniform fast path. The host must still provide coherent time coordinates and establish the required committed history.

Adaptive dt (LTE-controlled SPICE)

Let dt_runtime follow the solver's local truncation error control:

const double model_dt = info.dt;
for (...) {
    double dt = solver_proposed_dt();
    /* Clamp to [0.1 * model_dt, 10 * model_dt] for typical EDA scenarios */
    if (dt < 0.1 * model_dt) dt = 0.1 * model_dt;
    if (dt > 10.0 * model_dt) dt = 10.0 * model_dt;

    tdse_step_begin(model, t, dt);
    /* ... */
    tdse_step_commit(model, primary, np);
    t += dt;
}

Host/TDSE split here:

  • the host proposes and clamps dt
  • TDSE interprets the accepted (t, dt) against model_dt
  • interpolation error belongs to the integration policy, not to Runtime

Trace Replay

When primary comes from an external trace file with trace_dt != model_dt:

  • Option A: drive the runtime with trace_dt directly (time-driven interpolation).
  • Option B: resample the trace to model_dt externally, then use the fast path.

They are not bitwise or numerically identical in general: Option A uses Runtime's interpolation at fixed model delays, while Option B adopts the external resampler's interpolation/filtering policy. Option B can enable the uniform fast path when the host also supplies an aligned, uniform committed timeline. TDSE privately selects the implementation for the model's configured device; applications do not select an internal backend for this path.

Decision Table

If your main goal is...Start with...Escalate to...
fastest bring-upfixed dt_runtime = model_dtnothing until basic loop is stable
adaptive solver fidelityclamped adaptive dterror measurement and tuning
multi-rate orchestrationone handle per rateexplicit scheduling and cross-model review

Related API

  • tdse_step_begin(model, t, dt) in tdse/tdse.h: core entry point discussed here
  • tdse_model_info_t.dt in tdse/tdse.h: query model_dt
  • tdse_ext_context_get_runtime_guard_metrics() in tdse_ext.h: runtime stability monitoring
  • tdse_builder_compute_consistent_grid() in tdse_builder.h: derive consistent model_dt, nh, nfft, and dw at build time