Theory and Concepts
Why TDSE exists, how the method is partitioned, and which modeling assumptions shape integration choices.
Audience: Anyone who wants to understand what TDSE computes and why, before reading the API chapters. If you only need the fastest path to a working build, skip ahead to Getting Started and come back when you need to understand what the step-loop terms mean.
Use this chapter when you want the math behind TDSE to feel concrete enough to guide implementation choices. It links each concept to the Builder and Runtime operations you see later in the handbook, so the theory stays connected to code.
If you have already finished Hands-On Tutorial but the roles
of op, hr, ir, dr, trial, and commit still feel abstract, read this
chapter before you go deeper into the Runtime chapters.
Why TDSE Exists
The Problem with Conventional Solvers
Many engineering simulations involve dynamic systems whose time-domain behavior is described by differential equations. After spatial discretization or lumped-parameter modeling, these systems are typically expressed as ordinary differential equations (ODEs) or differential-algebraic equations (DAEs).
When a large linear subsystem is re-solved at every simulation time step, even though its linear characteristics have not changed, the repeated processing can introduce three compounding problems:
-
Excessive computational cost. For dense direct solves, a global linear solve can scale roughly as
O(N^3)in the number of degrees of freedom. Sparse and structured solvers reduce that cost, but repeated factorization or solve work can still dominate large coupled simulations. -
Numerical error accumulation. Repeated matrix factorizations and global solves accumulate rounding errors, particularly in the presence of high-frequency dynamics or stiff coefficients.
-
Scalability limits. Model-reduction techniques such as modal truncation and static condensation reduce cost, but the accuracy trade-off must be checked against the frequency range and coupling behavior that matter to the host simulation.
The Impulse-Response Approach
TDSE takes a different path. Instead of re-solving the linear subsystem at every step, it processes the linear part once during a pre-computation phase and then reuses the result throughout the simulation through a convolution operation.
The key insight is:
- The linear subsystem is time-invariant. Its response to any port input can be fully characterized by a single impulse-response sequence.
- Cross-subsystem coupling can be decomposed into three computable terms: an independent-response term, a historical convolution term, and an instantaneous term.
- These terms are incorporated into the governing equation of the nonlinear subsystem, forming an equivalent equation that can be solved without ever re-opening the linear subsystem.
Complexity Reduction
| Approach | Per-Step Cost | Notes |
|---|---|---|
| Conventional dense global solve | O(N^3) | N = total system degrees of freedom; sparse or structured solves can scale differently |
| TDSE convolution | O(P^2 · L) | P = number of ports, L = effective impulse-response length |
In practical engineering systems, P is often much smaller than N (for example, tens of ports versus thousands of internal states). This is the main reason TDSE can reduce per-step work while retaining the frequency-domain detail represented by the input data and fitting choices.
When TDSE Is the Right Choice
TDSE is designed for dynamic systems that can be partitioned into:
- a linear time-invariant subsystem whose characteristics do not change during simulation
- a nonlinear and/or time-varying subsystem that must be solved step-by-step
Typical application domains include:
| Domain | Examples |
|---|---|
| Electrical / Electronic | power electronics, EMI/EMC, transmission-line networks |
| Mechanical / Structural | structural dynamics, multibody systems, vibration analysis |
| Hydraulic / Pneumatic | servo systems, fluid power networks |
| Thermal | heat transfer, thermo-mechanical coupling |
| Electromagnetic | transient EM, electromagnetic compatibility |
| Fluid dynamics | fluid motion, thermo-fluid-solid coupling |
| Control systems | controller-in-the-loop, plant-controller co-simulation |
| Multi-physics | any coupled system mixing the above domains |
Core Concepts
The terms below are the ones that matter most when you move between theory, Builder inputs, and the Runtime step loop. Each definition is paired with the SDK operation that makes it visible in practice.
Dynamic System
A physical, engineering, or computational system whose state variables evolve over time. Described by time-domain equations relating state variables, their time derivatives, and inputs.
SDK mapping: the entire model you build and run through Builder + Runtime.
Generalized Differential Equations
The mathematical formulation used to describe dynamic system behavior during numerical simulation. Includes ODEs, DAEs, and semi-discrete equations obtained after spatial discretization (finite-element, finite-volume, finite-difference, boundary-element, or spectral-element methods).
SDK mapping: the equations that the host solver integrates. TDSE does not solve them directly; it provides operator terms that the host incorporates into its own solve.
System Partitioning
Splitting a coupled dynamic system into two interacting parts for numerical analysis:
- First subsystem (linear, time-invariant): processed once; its characteristics are captured as precomputed data
- Second subsystem (nonlinear, time-varying, event-driven): solved step-by-step by the host
Interactions between subsystems are represented through port variables.
SDK mapping: this is a modeling decision made upstream of the SDK. The SDK assumes partitioning
is already complete when you provide H and IR artifacts.
Port Function
A functional relationship that describes coupling between subsystems through one or more interface variables. A port function represents how an output quantity of one subsystem influences an input quantity of another.
Port variables are physically meaningful conjugate pairs representing energy or signal exchange: voltage/current in electrical systems, force/displacement in mechanical systems, pressure/flow in hydraulic systems.
SDK mapping: the dimension np (number of primary inputs / ports) that you configure in Builder
and that the host primary vector must match.
Impulse-Response Sequence (H)
A discrete-time sequence h[n] that characterizes how the linear subsystem responds over time to a
unit impulse applied at a port. It captures the time-domain transfer behavior of the linear subsystem.
For multi-port systems, the impulse response is a three-dimensional array indexed by
(time lag, output port, input port).
SDK mapping: the H tensor you pass to tdse_builder_apply_h(). Layout: [nh][nq][np].
At runtime, H[0] becomes the instantaneous operator (op), and H[1..nh-1] contribute to the
delayed-history term (hr).
Independent-Response Sequence (IR)
A discrete-time sequence x0[n] that characterizes the intrinsic dynamic behavior of the linear
subsystem under a zero-input condition (i.e., when coupling inputs from other subsystems are not applied).
It represents the "free response" of the subsystem.
SDK mapping: the IR sequence you optionally pass to tdse_builder_apply_ir().
At runtime, it is queried via tdse_step_ir().
Historical Term
A contribution generated through time-domain convolution of the impulse-response sequence with past values of port input quantities. It represents accumulated effects of prior subsystem interactions over time.
In the convolution sum:
historical = sum_{k=0}^{n-1} h[n-k] * y[k]
SDK mapping: the hr vector returned by tdse_step_hr(). Length is nq.
Instantaneous Term
A contribution associated with the zero-time component of the impulse-response sequence. It represents the immediate coupling effect at the current simulation time.
In the convolution sum:
instantaneous = h[0] * y[n]
SDK mapping: the op operator returned by tdse_step_op(). Shape is nq x np (full view)
or np x np (square view).
Equivalent Equation
The reformulated governing equation of the nonlinear subsystem, constructed by incorporating the three terms above:
g(y, dy/dt, ..., t) = x0[n] + (historical) + (instantaneous) * y[n]
This equivalent equation can be solved using standard time-stepping integration without ever re-solving the linear subsystem.
SDK mapping: the trial-solve relation that the host evaluates each step:
y_trial = op * primary_trial + hr + ir
Numerical Time-Stepping Integration
The process of advancing a numerical solution of time-domain equations forward in time using discrete time steps. The time steps may be fixed or variable, and the integration may employ explicit, implicit, or semi-implicit schemes.
SDK mapping: the host-owned simulation loop that calls tdse_step_begin/op/hr/ir/commit
each step. TDSE supplies the operator terms; the host owns the integration strategy.
The Four-Step Method
The TDSE framework is organized around four processing steps. Steps 1-3 happen during pre-computation (before the simulation loop). Step 4 is the runtime loop itself.
Step 1. System Partitioning
What happens: The coupled dynamic system is divided into a linear time-invariant first subsystem and a nonlinear/time-varying second subsystem. Port functions define the coupling interface.
In practice: This is a modeling decision. You decide which portions of your system are linear and extract their frequency response or time-domain characteristics using your own tools or the TDSE Adapter layer (currently Adapter Circuit for circuit-domain workflows).
SDK entry points: Adapter Circuit commands (tdse adapter circuit matrix, tdse adapter circuit series)
produce the FRF/port data that feeds into Builder.
Step 2. Linear Subsystem Characteristic Computation
What happens: The computing device computes two discrete sequences for the linear subsystem:
- Independent-response sequence
x0[n]— the free response under zero coupling input - Impulse-response sequence
h[n]— the response to a unit impulse at each port
SDK entry points: If you have frequency-domain data, tdse_builder_h_from_spectrum() performs
the frequency-to-time conversion internally. If you already have time-domain H, pass it directly
to tdse_builder_apply_h().
Step 3. Equivalent Equation Construction
What happens: Using the impulse-response sequence, cross-subsystem coupling is analytically decomposed into three terms and incorporated into the governing equation of the nonlinear subsystem:
| Term | Meaning | Pre-computable? |
|---|---|---|
| Independent-response | free response of the linear subsystem | yes |
| Historical | convolution of past port inputs with impulse response | yes (from past steps) |
| Instantaneous | current-step coupling via h[0] | combined with host solve |
The instantaneous term is folded into the left-hand-side operator of the nonlinear subsystem, so the equivalent equation retains the same structural form as the original DAE/ODE.
SDK entry points: This decomposition happens automatically inside Builder when it writes the
pack. At runtime, tdse_step_op(), tdse_step_hr(), and tdse_step_ir() expose the three terms.
Step 4. Time-Domain Numerical Solution
What happens: The host advances the equivalent equation through time-stepping integration. Because the linear dynamics have already been incorporated via convolution, each step only needs to solve the nonlinear subsystem locally — no global linear solve is required.
SDK entry points: The runtime step loop: tdse_step_begin -> tdse_step_op / tdse_step_hr /
tdse_step_ir -> host solve -> tdse_step_commit.
Partitioning Your System
System partitioning is the single most important modeling decision when using TDSE. The guidance below is meant to help you make that split once, cleanly, before you build a pack.
Linear vs Nonlinear: The Split
The first subsystem should contain everything that is:
- linear: superposition applies; no state-dependent coefficients
- time-invariant: coefficients do not change with time or with operating point
Everything else goes into the second subsystem: nonlinear elements, time-varying parameters, switches, event-driven components, control logic.
Port Variables
The interface between subsystems is defined by port variables. Each port carries a pair of conjugate physical quantities:
| Domain | Effort variable | Flow variable |
|---|---|---|
| Electrical | voltage | current |
| Mechanical | force | displacement |
| Hydraulic | pressure | flow rate |
| Thermal | temperature | heat flow |
The number of ports (np in the SDK) is the number of independent interface channels.
Choosing fewer ports reduces per-step cost (O(P^2 · L)) but may coarsen the coupling representation.
Practical Partitioning Guidelines
-
Put all linear passive networks in the first subsystem. Transmission lines, RLC networks, structural matrices, and thermal conductance networks are typical candidates.
-
Put switches, nonlinear devices, and controllers in the second subsystem. Power electronics switches, diode characteristics, contact elements, and controller logic change behavior during simulation and cannot be pre-characterized.
-
Choose ports at natural physical interfaces. Wherever you would place a measurement probe or a boundary condition is usually a good port location.
-
Minimize port count when possible. If two ports always carry the same signal (redundant coupling), consider merging them. Cost scales with P^2.
What If the System Cannot Be Cleanly Partitioned?
Some systems have linear elements whose parameters depend on operating-point quantities computed by the nonlinear subsystem (e.g., a temperature-dependent resistance). In such cases:
- If the parameter variation is slow relative to the simulation dynamics, treat it as approximately constant and re-build the pack when the operating point changes significantly.
- If the variation is fast, consider placing the element in the nonlinear subsystem.
Obtaining the Impulse Response
The impulse-response sequence H is the central pre-computed artifact in the TDSE framework.
There are three paths to obtain it.
Path Comparison
| Path | Input Data | Best When | SDK Support |
|---|---|---|---|
| Time-domain | Direct simulation of impulse excitation | You already have a time-domain solver for the linear subsystem | Direct H via tdse_builder_apply_h() |
| Frequency-domain | Frequency response function (FRF) at discrete frequencies | Your upstream tools produce FRFs (e.g., AC sweep from circuit simulator) | tdse_builder_h_from_spectrum() |
| Modal decomposition | Eigenstructure or modal parameters | You have dominant mode information from FEA or modal analysis | Convert to H externally, then tdse_builder_apply_h() |
Frequency-Domain Path in Detail
When your source data is a frequency response function H(w), the conversion to a time-domain impulse response involves:
- Frequency sampling. Define a positive-frequency grid
omega[k]covering the bandwidth of interest. - Inverse transform. Compute the discrete inverse Fourier transform to obtain the time-domain sequence.
- Causality correction. Band-limited frequency data can produce non-causal (pre-response) artifacts in the time domain. The computing device applies correction to enforce physical causality.
- Truncation and windowing. The resulting sequence may need to be truncated to a practical length and windowed to suppress high-frequency ringing.
Steps 2-4 are handled internally by tdse_builder_h_from_spectrum().
Causality Correction Guide
When converting frequency-domain data to time-domain impulse responses, the finite frequency sampling bandwidth can introduce non-physical artifacts. Causality correction restores physical consistency.
The Builder exposes four correction methods. The goal here is to show what each one changes and how to choose without guesswork.
Two Families of Correction
Correction methods fall into two families, depending on which part of the frequency response you use to recover the full complex spectrum.
Family A: Real/Imaginary Component Methods
For a causal linear time-invariant system, the real and imaginary parts of the frequency response satisfy reciprocal Hilbert-transform relationships (Kramers-Kronig). Given one component, the other can be reconstructed.
Family B: Magnitude/Phase Methods
For minimum-phase systems, logarithmic magnitude and phase are coupled analytically. Given either magnitude or phase, the other can be reconstructed via a Hilbert transform of the logarithmic magnitude.
Builder Correction Methods
| Method | Family | Input | What It Does | When to Use |
|---|---|---|---|---|
Reconstruct from Real (TDSE_BUILDER_CORRECTION_RECONSTRUCT_FROM_REAL) | A (real/imag) | Real part of FRF | Recovers the full complex spectrum from the real part via Kramers-Kronig. Preserves total energy and DC component. | General-purpose default; works well when the real part is reliable |
Reconstruct from Imag (TDSE_BUILDER_CORRECTION_RECONSTRUCT_FROM_IMAG) | A (real/imag) | Imaginary part of FRF | Recovers the full complex spectrum from the imaginary part. Suppresses even-symmetric response components that cause pre-response artifacts. | When the imaginary part is more reliable, or when FRF data shows symmetric artifacts |
Reconstruct from Magnitude (TDSE_BUILDER_CORRECTION_RECONSTRUCT_FROM_MAG) | B (mag/phase) | Magnitude only | Derives phase from log-magnitude via minimum-phase Hilbert transform, recovering the full complex spectrum. | When only magnitude data is available or reliable; phase is missing or noisy |
Reconstruct from Phase (TDSE_BUILDER_CORRECTION_RECONSTRUCT_FROM_PHASE) | B (mag/phase) | Phase only | Derives magnitude from phase via Hilbert transform, recovering the full complex spectrum. | When only phase data is available or reliable; magnitude is missing or noisy |
Selection Guide
What frequency-domain data do you have?
├─ Real part of FRF → Reconstruct from Real (general-purpose, energy-preserving)
├─ Imaginary part of FRF → Reconstruct from Imag (suppresses symmetric artifacts)
├─ Magnitude only → Reconstruct from Magnitude
└─ Phase only → Reconstruct from Phase
Correction Method vs. Pack Quality
The correction method directly affects the numerical behavior of the resulting pack:
- Wrong choice can produce: non-causal pre-responses, energy drift, or spectral distortion.
- Right choice ensures: causal impulse response, energy consistency, and stable convolution behavior.
If you are unsure, start with Reconstruct from Real and compare runtime results against a known reference. Switch only when you can verify the change improves accuracy for your specific system.
IMPORTANT: Once a pack is written, Runtime sees only the resulting
Htensor. It has no knowledge of which correction method was used. Support triage should always separate the question "did Builder construct the intended H?" from "did Runtime execute the pack correctly?"
Practical Considerations
Truncation and Windowing
The impulse response of a linear subsystem typically has a finite but non-strictly-bounded duration. Directly using an unprocessed sequence within a finite numerical window can introduce:
- High-frequency ringing from abrupt truncation
- Spectral leakage in subsequent convolution operations
Mitigation strategies applied during pre-computation:
- Truncation: limit the impulse response to
nhtaps (thenhparameter in Builder configure). Choosenhlarge enough to capture the significant dynamic content. - Windowing: apply a tapering window (e.g., exponential decay, half-cosine) to the tail of the sequence to smooth the truncation boundary and suppress ringing.
SDK mapping: nh in tdse_builder_options_t controls the history depth. Larger nh captures
more dynamic content but increases per-step cost.
Resampling and Interpolation
The impulse-response sequence is precomputed at a fixed sampling interval, but the host integrator may use a different step size (especially under variable-step schemes).
When the convolution time grid does not align with the integration grid, the computing device interpolates or resamples the sequence to maintain:
- Time alignment between convolution terms and the numerical integrator
- Energy consistency of accumulated convolution contributions
- Numerical stability of the overall stepping process
SDK mapping: When h_desc.tau is provided, the H tensor must already be weighted for the
explicit time axis. Use tdse_h_uniform_to_tau_1d() or tdse_h_uniform_to_piecewise_tau_1d()
to convert uniform-grid taps to an explicit axis before passing them to Builder.
Variable Time-Step Integration
In variable-step integration, the step size may change from one step to the next. TDSE accommodates this through the resampling mechanism: before each step, the impulse-response and independent-response sequences are re-evaluated on the current integration grid.
The practical implication for host integrators:
- The
dtpassed totdse_step_begin()can differ from step to step - Convolution terms remain properly aligned across different time scales
- Energy consistency is maintained automatically
Multi-Port Convolution
For systems with multiple coupled ports, the impulse response becomes a three-dimensional array where each input port has its own set of response traces at all output ports.
During simulation, convolution is performed in parallel along the port dimension. The per-step
computational cost scales as O(P^2 · L) where P is the number of ports and L is the effective
impulse-response length.
SDK mapping: the H tensor shape [nh][nq][np] directly encodes this multi-port structure.
At runtime, tdse_step_op() returns the full nq x np operator, and tdse_step_hr() returns
the nq-length history vector that already accounts for all port interactions.
First Subsystem State Reconstruction
After completing the simulation of the nonlinear subsystem, the time-domain response of the linear subsystem can be reconstructed using the convolution expression:
x[n] = x0[n] + sum_{k=0}^{n-1} h[n-k] * y[k]
This is a post-processing step: substitute the solved y[n] (from the second subsystem) into
the convolution formula to recover the linear subsystem state trajectory.
SDK mapping: TDSE Runtime does not perform this reconstruction automatically. The host can
implement it using the committed primary vectors and the original H and IR data.
Pack Representation: Y+ISC vs Z+VOC
The pack stores not only the numerical H and IR arrays but also a representation label that tells
downstream consumers what physical meaning the port variables carry. Understanding this label is
essential when your model contains an independent-response sequence (IR).
Two Canonical Representations
| Representation | Form | Port Input (primary) | Port Output (secondary) | Relationship |
|---|---|---|---|---|
| Y + ISC | FLOW_FROM_EFFORT | effort variable (e.g., voltage) | flow variable (e.g., current) | i = Y * v + ISC |
| Z + VOC | EFFORT_FROM_FLOW | flow variable (e.g., current) | effort variable (e.g., voltage) | v = Z * i + VOC |
The terminology comes from electrical engineering but the concept generalizes:
| Domain | Effort (Y+ISC input) | Flow (Y+ISC output) |
|---|---|---|
| Electrical | voltage | current |
| Mechanical (translational) | displacement | force |
| Hydraulic | pressure | flow rate |
| Thermal | temperature | heat flow |
Why It Matters
The representation determines how the host must interpret the step-loop terms:
- In Y + ISC mode,
primaryis the effort vector,opis an admittance,hr + irform the short-circuit current contribution, anddrgives the current response. - In Z + VOC mode,
primaryis the flow vector,opis an impedance,hr + irform the open-circuit voltage contribution, anddrgives the voltage response.
The math inside Runtime is identical in both cases — the same convolution engine runs — but the host
must know which physical convention applies to correctly wire primary, interpret dr, and couple the
result back into the nonlinear subsystem.
Setting the Representation
tdse_builder_set_pack_meta(b,
TDSE_PACK_FORM_FLOW_FROM_EFFORT, /* or TDSE_PACK_FORM_EFFORT_FROM_FLOW */
TDSE_PACK_DOMAIN_ELECTRICAL); /* domain hint for downstream tooling */
When IR is present, setting the representation is not optional. The IR sequence has different
physical meaning depending on whether it represents ISC (short-circuit current) or VOC (open-circuit
voltage).
When Representation Is Ambiguous
For packs without IR, TDSE_PACK_FORM_UNKNOWN is acceptable because the convolution math is
representation-independent. But once IR is attached, leaving the form as UNKNOWN creates a
support hazard: downstream users cannot tell whether the IR term should be added to an admittance
equation or an impedance equation.
If your team cannot answer which representation the pack carries, do not write the pack yet. Resolve the ambiguity at the Builder stage — it cannot be fixed later at the Runtime stage.
EMT Simulator Integration
The mapping below is for readers who already think in EMT solver equations and want to line those terms up with the TDSE step loop.
Norton Equivalent Interpretation
The TDSE step-loop trial equation:
y_trial = op * primary_trial + hr + ir
takes a direct Norton equivalent form in the EMT nodal equation:
G_eff * v(n+1) = J_history + J_source
The mapping is:
| EMT Term | TDSE Term | Meaning |
|---|---|---|
G_eff | op (from tdse_step_op) | Effective nodal conductance matrix (instantaneous operator H[0]) |
J_history | hr (from tdse_step_hr) | History current source from delayed convolution of past port voltages |
J_source | ir (from tdse_step_ir) | Independent-response current source (ISC: short-circuit current under zero coupling voltage) |
v(n+1) | primary_trial | Port voltage vector at the next time point |
i(n+1) | y_trial | Port current vector (the Norton injection) |
In Y+ISC representation (admittance form):
i(n+1) = Y_eff * v(n+1) + ISC_history + ISC_source
Where:
Y_eff = opis the instantaneous admittance looking into the linear subsystemISC_history = hris the convolution history currentISC_source = iris the independent-source current (the linear subsystem's free response)
In Z+VOC representation (impedance form), the roles swap:
v(n+1) = Z_eff * i(n+1) + VOC_history + VOC_source
Integration with EMT Nodal Solve
A typical EMT solver builds a global nodal equation at each time step:
G_global * v_global(n+1) = J_global(n+1)
When TDSE represents a linear subsystem, the host injects the TDSE Norton equivalent into the global equation:
-
Stamp
opinto the global conductance matrix. Addop[row, col]to the corresponding entries ofG_globalat the port node positions. This is identical to stamping a conductance matrix from a conventional companion model. -
Stamp
hr + irinto the global RHS vector. Addhr[row] + ir[row]toJ_globalat the port node positions. This is the history plus source injection. -
Solve the global system. The EMT solver solves
G_global * v = J_globalas usual. -
Extract the accepted port voltages. After the global solve, extract the port voltage solution as
primary_accepted. Calltdse_step_commit(model, primary_accepted). -
Advance history. The commit call updates internal convolution history. The next
tdse_step_hrcall will incorporate the just-accepted port voltages.
Worked Example: Single-Port Transmission Line
Consider a 500 kV, 100 km single-phase transmission line with characteristic admittance Y_c and propagation delay tau:
i(t) = Y_c * v(t) + h_history(t)
In TDSE terms:
np = nq = 1(single port)op = Y_c(the instantaneous characteristic admittance)hr = h_history(the reflected-wave history from past terminal voltages)ir = 0or a known source injection (if the remote end has a known waveform)
The integration into a 50 us EMT step loop:
/* Inside the EMT solver main loop, at the transmission line port: */
tdse_step_begin(model, t, dt);
double op_val;
tdse_dense_block_t op_blk = { ... };
tdse_step_op(model, &op_blk); /* op = Y_c */
double hr_val, ir_val;
tdse_step_hr(model, &hr_val); /* hr = reflected wave contribution */
tdse_step_ir(model, &ir_val); /* ir = remote-end source (if any) */
/* Stamp into global EMT nodal equation */
G_global[port_node][port_node] += op_val;
J_global[port_node] += hr_val + ir_val;
/* After global solve: */
double v_port = v_solution[port_node]; /* extracted from global solution */
tdse_step_commit(model, &v_port);
/* Optional: read direct response */
double dr_val;
tdse_step_dr(model, &dr_val); /* dr = Y_c * v_port */
Key points:
- The TDSE model replaces the conventional Bergeron/traveling-wave companion model
- No explicit propagation delay bookkeeping in the host -- TDSE handles it through the convolution history
- The host only stamps conductance and current, then extracts the solution voltage
- Multi-port lines or cables use
np > 1with the same pattern:opisnp x npandhr,irarenp-length vectors
EMT Integration Anti-Patterns
Avoid these common mistakes when embedding TDSE in an EMT solver:
-
Double-stamping conductance. If the host already has a companion model for the same port nodes, remove it before stamping
op. The TDSE operator replaces the conventional companion, it does not supplement it. -
Confusing Y+ISC with Z+VOC. In Y+ISC mode,
primaryis voltage andy_trialis current (injection). In Z+VOC mode,primaryis current andy_trialis voltage. Stamping the wrong form into the nodal equation produces silently incorrect results. -
Committing before the global solve. The commit must use the accepted port voltages from the global solution, not the trial voltages. The sequence is: query terms -> global solve -> extract solution -> commit.
-
Ignoring the prime step. EMT solvers typically start from steady-state initial conditions. The TDSE prime step at
n = -1establishes the initial history. If the host has known initial port voltages, use those asprimary_minus1in the prime commit.
Multi-Port Subsystem Integration
For N-port subsystems (e.g., a multi-conductor cable or a transformer equivalent):
G_global[node_i][node_j] += op[row][col] /* for each port pair */
J_global[node_i] += hr[row] + ir[row] /* for each port */
Where the mapping between TDSE port indices (row, col) and EMT global node indices (node_i, node_j) depends on how ports were defined during system partitioning.
The nq > np case allows the host to access additional output equations beyond the port count. In EMT terms, this corresponds to internal measurements (e.g., receiving-end voltage of a transmission line) without adding extra port nodes to the global system.
Numerical Accuracy Considerations
The goal here is to turn the accuracy story into engineering guidance: where error enters the TDSE pipeline, and which parts usually matter most.
Spectrum-to-H Conversion Accuracy
The frequency-domain-to-time-domain conversion performed by tdse_builder_h_from_spectrum() introduces error from three sources:
| Error Source | Magnitude | Mitigation |
|---|---|---|
| Finite bandwidth truncation | depends on spectral content beyond w_max = pi/dt | ensure dt captures highest significant frequency |
| Causality correction | method-dependent (see below) | choose correction method based on data completeness |
Windowing/truncation at nh | O(h[nh]) -- the tail value at truncation | verify H[nh-1] is negligible |
Correction method accuracy comparison:
| Method | Typical Error | Best Case | Notes |
|---|---|---|---|
| None | high (non-causal pre-response visible) | N/A | Not recommended for production |
| Reconstruct from Real | < 1% energy error for well-sampled FRF | < 0.1% for dense uniform grids | General-purpose default |
| Reconstruct from Imag | < 0.5% for data with even-symmetric artifacts | < 0.1% | Better when FRF has symmetric truncation artifacts |
| Reconstruct from Magnitude | 5-15% magnitude error typical | < 2% for minimum-phase systems | Phase accuracy depends on Hilbert transform quality |
| Reconstruct from Phase | 5-15% phase error typical | < 2% | Only when phase is missing/unreliable |
Verification: After conversion, compare the time-domain impulse response against the expected physical behavior. The first sample H[0] should be real-valued (no imaginary component for a real system). The tail H[nh-1] should decay to near the machine epsilon or at least below the application's accuracy requirement.
IRC Compression Accuracy
Builder IRC compresses the tail of the impulse response into exponential decay parameters. The accuracy is controlled by tail_tolerance:
tail_tolerance | Typical Pack Size Reduction | Accuracy |
|---|---|---|
| 1e-4 | 50-70% | moderate; acceptable for initial screening |
| 1e-6 | 30-50% | good; suitable for most power-system applications |
| 1e-8 | 15-30% | high; recommended for production accuracy |
| 1e-10 | 5-15% | very high; marginal compression benefit |
The error bound is: the compressed tail differs from the original by at most tail_tolerance per tap in the L2 sense.
Verification: Run the Profiler IRC scan (tdse profiler irc-scan) to compare compressed vs. uncompressed results before committing to production.
FP32 vs FP64 History Precision
When tdse_compute_precision_set(model, TDSE_COMPUTE_PRECISION_FP32) is used, the history convolution uses single-precision accumulation:
| Precision | Per-tap rounding error | Cumulative error for nh taps | Recommended when |
|---|---|---|---|
| FP64 (default) | ~2.2e-16 | negligible | always preferred for accuracy |
| FP32 | ~1.2e-7 | up to nh * 1.2e-7 | nh < 1000 and application tolerates ~1e-4 relative error |
Guideline: Use FP32 only when nh is large enough that the performance benefit outweighs the accuracy cost, and when the host application's error budget can absorb the additional ~nh * 1.2e-7 perturbation in the history term.
Truncation and Windowing
The impulse response is truncated to nh taps. The truncation error is:
E_trunc = sum_{k=nh}^{infinity} |h[k]|^2
Practical rule: verify that |H[nh-1]| is at least 40 dB below |H[0]| (i.e., the tail has decayed by a factor of 100 or more). If not, increase nh and rebuild the pack.
Accuracy Verification Workflow
- Build pack with generous
nh(e.g., 2x the expected minimum) - Run a reference simulation with known analytical solution
- Measure the error:
|y_TDSE - y_exact| / |y_exact| - If error exceeds tolerance:
- Check if
H[nh-1]has decayed sufficiently - Try a different causality correction method
- Compare compressed (IRC) vs. uncompressed results
- Switch from FP32 to FP64 history precision
- Check if
- Archive the accuracy verification alongside the pack for release evidence
Now Continue Here
Once the conceptual model is clear, use the next chapter based on the question you actually need to answer:
| If you need to... | Go next |
|---|---|
| choose the right Runtime API family quickly | Runtime API Summary |
package validated H or IR data into a pack | Builder and Data Contracts |
| understand create / destroy / ownership behavior | Runtime Lifecycle |
| understand the trial / commit simulation loop | Step Execution |
