Time-Domain System Equivalent logoTime-Domain System EquivalentLinear dynamics, solved faster.Discuss Integration

Builder and Data Contracts

Builder inputs, data contracts, pack creation, and the main integration flow.

Use this chapter when you already have validated H data, optional IR data, or source data that Builder can convert, and you need to produce a pack that Runtime can load. It explains the Builder setup flow, the shape rules that matter at the handoff, and the checks worth running before you blame Runtime for a bad pack. This chapter stops at the pack-to-runtime handoff; the full runtime lifecycle and step loop live in their own chapters.

If your starting point is already FRF data, impulse-response data, or a Builder-ready workflow output, start here. If your starting point is a circuit netlist, RAW case, or Touchstone-driven circuit flow, start with Adapter Circuit instead.

Related Chapters For Runtime lifecycle semantics after pack creation, see Runtime Lifecycle. For step execution inside the simulation loop, see Step Execution.

Use this chapter when your integration starts from one of these Builder-side artifacts:

Starting artifactBuilder role
validated H tensorattach H, write pack, hand off to Runtime
validated H plus optional IRattach both, preserve shape and horizon contracts
matrix or circuit workflow outputaccept Builder-ready handoff from Adapter or workflow API

Prerequisites

  • Built SDK artifacts (Runtime tdse, Builder tdse_builder, headers).
  • A generated pack input (H required, IR optional).
  • Build/test workspace ready:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

Quick Start

Both paths below end with a written pack and a small handoff check. Use the minimal path for prototyping; switch to the production path before release.

Minimal path

tdse_builder_t* b = NULL;
tdse_builder_options_t cfg = tdse_builder_options_init();
cfg.dt = dt;
cfg.nh = nh;
cfg.np = np;
cfg.nq = nq;
tdse_builder_create(&b);
tdse_builder_configure_ex(b, &cfg);        /* np/nq/nh/dt */
tdse_builder_apply_h(b, &h_desc);          /* required */
tdse_builder_apply_ir(b, &ir_desc);        /* optional */
tdse_builder_write_pack(b, "model.pack");
tdse_builder_destroy(b);

Then hand the pack to Runtime Lifecycle for create/destroy behavior and to Step Execution for the simulation loop.

Minimal host-side interpretation:

  • Builder owns pack construction and pack metadata
  • Runtime owns create, step, and destroy after pack bytes are handed off
  • the host owns artifact selection, pack storage, and when to start Runtime

Production path

For production integration, add these practices on top of the minimal flow:

  1. Validate pack bytes before runtime create (tdse_pack_validate).
  2. Inspect the pack summary before create so shape and metadata mismatches are visible early.
  3. Archive a Builder snapshot (tdse_builder_info(...)) next to the pack or release artifact.
  4. Run one deterministic runtime smoke check: create the model, read tdse_model_info(...), and verify a known-good step path.
  5. Archive tdse_model_create_diagnostics_t on non-OK create paths.
  6. Run threading stress and contract tests before promoting binaries.

Runtime handoff note:

Smallest Supported Builder -> Runtime Handoff

If your team needs the shortest credible integration contract, treat the handoff as these four checks:

  1. Builder writes one pack successfully
  2. tdse_pack_validate accepts that pack
  3. Runtime create succeeds and tdse_model_info(...) matches expected np, nq, nh, and dt
  4. one prime-and-step smoke path completes without status errors

Validation Checklist

  • tdse_pack_validate passes on release pack.
  • Minimal step loop returns TDSE_OK end-to-end.
  • One failure-injection case per major status is covered.
  • Threading stress case is green on target build.
  • Runtime outputs are stable across repeated runs with same input.
  • Linux deployment claims match the current RuntimeCore Linux support scope when shipping on Linux.

Parameter Cookbook

ParameterMeaningRecommended BaselineNotes
npprimary input countsystem-dependentMust match host primary vector width.
nqoperator row count>= npUse full rectangular view when nq > np.
nhhistory tapsstart with calibrated valueHigher nh raises history cost.
dtstep intervalfixed per modelKeep builder/runtime dt consistent.
IR lengthindependent sequence horizoncover whole simulation windowOut-of-range returns TDSE_ERR_IR_STEP_OUT_OF_RANGE.
runtime handlesparallel threadsone handle per workerNever step same handle concurrently.

Data Contracts

TDSE Core is strict about dimensions, layout, and ownership. Most early integration failures are shape mistakes rather than numerical mistakes.

Primary Dimensions

Four dimensions define most Builder-to-Runtime compatibility:

SymbolMeaningPractical Rule
npprimary input countmust match host primary vector width
nqoutput-equation countmust satisfy nq >= np
nhhistory tap lengthmust match the supplied H tensor depth
dtmodel step intervalmust be consistent across Builder and Runtime expectations

API Families

At the Builder boundary, the main API families are:

Builder lifecycle

  • tdse_builder_create
  • tdse_builder_configure_ex
  • tdse_builder_apply_h
  • tdse_builder_apply_ir
  • tdse_builder_write_pack
  • tdse_builder_destroy

Pack validation and inspection

  • tdse_pack_validate
  • tdse_pack_inspect
  • tdse_pack_inspect_ex
  • tdse_pack_error_token

Runtime handoff surface

  • tdse_model_create
  • tdse_model_info

For full Runtime lifecycle and step APIs, switch to Runtime Lifecycle, Step Execution, or Runtime API Summary.

Ownership Model

  • Builder descriptors such as tdse_h_desc_t and tdse_ir_desc_t are borrowed views
  • Pack-validation and pack-inspection outputs are caller-owned result structs
  • No Core API transfers ownership of caller-owned H, IR, or step-output buffers

Compatibility Equation

Builder-side and Runtime-side assumptions are compatible only when all of these are true:

  1. Builder np, nq, nh, and dt match the intended runtime model
  2. H is laid out exactly as declared by its descriptor
  3. optional IR is laid out exactly as declared by its descriptor
  4. runtime host buffers are sized from runtime-reported dimensions rather than from memory or guesswork

H Tensor Contract

H uses tap-major row-major storage: shape [nh][nq][np], linear index tap * nq * np + row * np + col, layout enum TDSE_H_LAYOUT_TAP_MAJOR_ROW_MAJOR.

  • H[0] is the instantaneous operator returned by tdse_step_op(...)
  • H[1..nh-1] contribute to the delayed-history term returned by tdse_step_hr(...)

Explicit-tau contract:

  • h_desc.tau == NULL means delayed taps live on the implicit uniform axis tau[k] = k * dt
  • h_desc.tau != NULL means Runtime evaluates history on the supplied explicit time axis
  • when tau is explicit, H[1..nh-1] must already be weighted for that axis
  • if your source taps came from a uniform grid, convert them first with tdse_h_uniform_to_tau_1d(...) or tdse_h_uniform_to_piecewise_tau_1d(...)

IR Sequence Contract

IR is step-major: shape [nsteps][nq], linear index step * nq + row, layout enum TDSE_IR_LAYOUT_STEP_MAJOR. Runtime queries IR by current step time. If the query falls outside the configured support window, tdse_step_ir(...) returns TDSE_ERR_IR_STEP_OUT_OF_RANGE.

Dense Operator Contract

tdse_step_op(...) writes into a tdse_dense_block_t. Supported views: square (np x np) or full (nq x np). cols must always equal np; rows must equal either np or nq.

Shape Worked Example

Assume np = 3, nq = 4, nh = 8, ir_nsteps = 100. Then:

QueryRequired Length / Shape
primary vector passed to commitlength np = 3
hr_out bufferlength nq = 4
ir_out bufferlength nq = 4
square op view3 x 3
full op view4 x 3
committed dr_out bufferlength nq = 4

The common bug: sizing hr, ir, or dr buffers to np because the host thinks in terms of ports rather than equations. These buffers are nq-sized outputs.

Step-Term Contract

For the mathematical definitions, see Theory and Concepts.

TermMeaningSide Effect
opinstantaneous operatornone
hrdelayed-history contributionnone
irindependent-response contributionnone
drcommitted-step direct responsequery-only, post-commit

Read these equations literally: y_trial = op * primary_trial + hr + ir; dr[n] = op * primary_accepted[n]. dr is the direct-response slice on the committed step, not "the whole committed output."

Runtime Handoff Contract

Builder is done once the pack is internally consistent, validated, and clearly labeled. The runtime handoff should answer three questions before any simulation work starts:

  1. does the pack validate cleanly
  2. do inspected dimensions and metadata match what the host expects
  3. does Runtime create the model without reporting pack or compatibility errors

After that point, move to Runtime Lifecycle and Step Execution instead of continuing to reason about Runtime behavior from the Builder chapter.

Host-Side Assertions

In production, assert these once near the integration boundary:

  1. model_info.np matches host primary-vector width
  2. model_info.nq matches host equation/output width
  3. model_info.nh matches intended history depth
  4. model_info.dt matches host time-step contract

Common Shape Mistakes

  • host primary vector width does not match np
  • hr/ir buffers sized to np instead of nq
  • square operator storage used when host required nq x np
  • Builder dt and simulation dt assumed to match without verification
  • inferring np/nq from old code paths instead of tdse_model_info(...)
  • treating IR as a runtime side channel instead of packaged model content

Power Systems Guide

Typical Parameters by Scenario

Scenariodt (s)nhnfftnpnqNotes
Transmission line (100 km, 500 kV)1e-6 to 10e-61000-50002 × nh2 (1 port) or 4 (2-port)np or np+1Large nh for propagation delay
Transformer (50 MVA)1e-6 to 50e-6200-10002 × nh2-6npModerate nh for winding capacitance
Distribution cable (underground)1e-6 to 10e-6500-20002 × nh2-4npnh depends on cable length
EMI/EMC (wideband)10e-9 to 100e-91000-40004 × nh1-10npVery fine dt for high-frequency content
Power electronics (switching ~100 kHz)10e-9 to 100e-9500-20002 × nh1-4npFine dt for switching transients

Choosing nh

The history depth nh must be large enough that H[nh-1] has decayed to near zero:

  1. Build the pack with an initial nh estimate
  2. Inspect H[k] for the last few taps (k near nh-1)
  3. If |H[nh-1]| is not negligible compared to |H[0]|, increase nh
  4. Typical transmission lines: nh ≈ round(propagation_delay / dt) + margin

For a 500 kV, 100 km line with propagation speed ~2.8×10⁸ m/s and dt = 50 μs: propagation delay ≈ 357 μs → nh ≈ 9. For dt = 1 μs: nh ≈ 367.

When to Use nq > np

Set nq > np when the model needs measurement equations beyond the port count: multi-port models with internal measurements, mixed Y/Z representations, or host simulators needing both terminal currents and internal state outputs. For standard Y+ISC or Z+VOC, nq = np is typical.

Builder Flow

Builder is the handoff layer between validated source artifacts and Runtime. A clear Builder boundary makes later debugging much easier: you can tell whether a problem comes from the source data, Builder configuration, pack generation, or Runtime execution.

Builder-to-Runtime responsibility split

Builder Responsibility

Builder owns the configured dimensions and dt, attachment of required H and optional IR, optional conversion from frequency-domain data into time-domain H, optional Builder-side shaping such as IRC, and the final pack metadata and pack write.

Builder does not own upstream artifact validity beyond descriptor and shape checks, host-specific port order or matrix-family interpretation, Runtime step execution, or Runtime shutdown and concurrency policy.

The main rule is simple: Builder should emit the final artifact, and Runtime should execute it as-is. Runtime is not expected to reconstruct or repair pack content later.

Builder State Machine

Builder state machine

Important rules: tdse_builder_configure_ex(...) is the recommended configure entrypoint, re-configuring replaces dimensions and clears previously attached H and IR, tdse_builder_info(...) is the best snapshot of the current Builder state, and a successful pack write does not transfer handle ownership.

Builder Contract Table

Contract ItemSet ByWhy It Matters Downstream
dttdse_builder_configure_ex(...)Runtime timing and IR step addressing
nptdse_builder_configure_ex(...)host primary vector width must match
nqtdse_builder_configure_ex(...)hr, ir, dr, and full op row count
nhtdse_builder_configure_ex(...)delayed-history horizon and H tensor depth
H layouttdse_h_desc_twrong layout produces plausible but incorrect packs
explicit tau axistdse_h_desc_tmalformed nonuniform timing rejected before pack write
IR layout and horizontdse_ir_desc_truntime tdse_step_ir(...) legality
pack form/domain metadatatdse_builder_set_pack_meta(...)support and consuming hosts interpret the pack

Direct H Ingestion

Use when the upstream artifact is already a validated time-domain kernel. Sequence: configure → populate tdse_h_desc_ttdse_builder_apply_h(...) → snapshot with tdse_builder_info(...) → write pack. Post-apply: verify info.configured, info.has_h, and dimension/tau expectations match.

Spectrum-to-H Conversion

Use tdse_builder_h_from_spectrum(...) when the upstream artifact is frequency-domain data.

The sequence: define positive-frequency grid → map source matrix into tdse_builder_cplx_mat_view_t → choose correction method → run conversion → attach → snapshot before write.

Correction methods:

  • TDSE_BUILDER_CORRECTION_NONE
  • _RECONSTRUCT_FROM_REAL
  • _RECONSTRUCT_FROM_IMAG
  • _RECONSTRUCT_FROM_MAG
  • _RECONSTRUCT_FROM_PHASE

These options change how Builder computes H; Runtime only sees the finished pack. When this path looks wrong, ask two separate questions: did Builder produce the intended H, and did Runtime execute that pack correctly?

Grid Planning: dt, nh, and nfft

These three parameters must satisfy nfft >= 2 * nh (FFT covers full impulse response without aliasing), dt must capture the highest source frequency, and nh * dt must capture full decay. Use tdse_builder_compute_consistent_grid(&grid) to compute consistent values from hints.

ScenariodtnhnfftRationale
Power electronics (~100 kHz)10-100 ns500-20002 × nhFine dt for switching edges
Transmission line (long delay)0.1-1 ns2000-100002 × nhLarge nh for delay + reflections
Structural dynamics (< 1 kHz)1-10 us200-10002 × nhCoarse dt sufficient
EMI/EMC (wideband)0.01-0.1 ns1000-40004 × nhLarge nfft for spectral resolution

Common mistakes: nh too small → truncated impulse response; dt too large → aliasing; nfft < 2*nh → wrap-around corruption.

FRF Data Layout

The source frequency-domain data must be organized as a row-major complex matrix: H_frf[freq_idx * np * nq + row * np + col]. The grid must be monotonically increasing, include near-DC, and use approximately uniform spacing. The Builder expects Y or Z parameters (not S-parameters). Multi-port ordering must be consistent across all frequency points.

Builder IRC (Impulse Response Compression)

IRC reduces effective history depth by compressing the tail of the impulse-response tensor. Two modes: V1 (single decay rate, most common) and V2 (per-tap adaptive decay, higher fidelity). Both retain the first prefix_len taps exactly and fit an exponential envelope to the tail.

tdse_builder_irc_options_t irc_opt = tdse_builder_irc_options_init();
irc_opt.mode = TDSE_BUILDER_IRC_MODE_V1;
irc_opt.prefix_len = 64;
irc_opt.tail_tolerance = 1e-8;
tdse_builder_apply_irc(b, &irc_opt);

Keep the IRC parameters next to the pack so later comparisons are reproducible. Use the Profiler IRC scan to explore compression quality before production use.

Optional IR

IR is optional, but once attached it becomes part of the pack Runtime will load. Keep Builder dt and IR dt aligned, keep IR dimensions aligned with np and nq, make sure the IR support length covers the simulation horizon, and set pack form metadata intentionally (FLOW_FROM_EFFORT = Y+ISC, EFFORT_FROM_FLOW = Z+VOC, UNKNOWN only for packs without IR).

Builder Inspection

tdse_builder_info(...) is the fastest way to confirm what Builder currently has attached. Use it after configure and after every attach or clear. Fields worth logging are configured, dt/nh/np/nq, has_h/has_h_tau/h_layout, has_ir/ir_nsteps/ir_dt/ir_layout, and pack_form/pack_domain. Once the pack is written, tdse_model_info(...) becomes the matching Runtime-side confirmation point.

Write Gate Checklist

Before tdse_builder_write_pack(...), confirm that Builder is configured, H is attached, dimensions match, optional IR is either absent or correctly attached, pack metadata is explicit, and the output path is stable. After the write, validate the pack, inspect it, then hand off to Runtime for create and loop verification.

Worked Paths

Path A: Direct-H Pack

Highest-confidence path: configure once → attach H → inspect → write → validate → create Runtime model. Fewest transformations; easiest to isolate failures.

Path B: Frequency-Domain Source To Pack

Archive the frequency grid and matrix family → run tdse_builder_h_from_spectrum(...) → attach → inspect → write → validate. Needs more release discipline because a successful write does not prove the conversion policy was correct.

Path C: H + IR With Explicit Pack Meaning

Configure → attach H → attach IRtdse_builder_set_pack_meta(...) intentionally → inspect → write → validate → create. Most likely to confuse downstream users if metadata is omitted.

Triage

Failure Modes

FailureSymptomRoot CauseFix
TDSE_ERR_IR_STEP_OUT_OF_RANGEtdse_step_ir fails mid-runSimulation time exceeds IR support windowExtend IR sequence or clamp simulation horizon
TDSE_ERR_CONCURRENT_API_USEsporadic non-OK in multi-thread runsame handle stepped by multiple threadsSerialize per handle; one handle per thread
TDSE_ERR_INVALID_ARGimmediate failure on create/stepnull/shape mismatch in inputsValidate pointers, dimensions, struct sizes
pack validation failurecreate rejects model bytescorrupted or incompatible packregenerate pack, inspect tdse_model_create_diagnostics_t

Builder Failure Classes Worth Catching Early

Failure ClassTypical Root CauseBest StageSupport Clue
dimension mismatchnp/nq/nh disagreementconfigure/applyBuilder snapshot vs. source planning sheet
malformed descriptornull pointer, bad struct size, invalid layoutapplyattach call fails immediately
tau-axis issueinvalid explicit nonuniform timingapply Hhas_h_tau vs. source timing mismatch
wrong matrix familyhost supplied wrong physical meaningpreflightpack validates but numerical behavior is wrong
IR horizon issuesequence shorter than intended runpreflight/attachRuntime fails at tdse_step_ir(...)
metadata ambiguityform/domain not set intentionallypre-write reviewcannot tell Y+ISC from Z+VOC
write-path issueunstable output path or file handlingpack writeconfigure/attach succeeded but no artifact exists

Builder-To-Runtime Failure Isolation

Builder-to-Runtime failure isolation

When a runtime test fails after a fresh pack write, split the investigation: did Builder produce the intended artifact, or did Runtime execute it incorrectly? This separation keeps teams from debugging the wrong layer.

Troubleshooting Decision Flow

Runtime troubleshooting decision flow

Rapid checks: prefer tdse_model_create(...) over process-global create diagnostics; log tdse_model_info once at model create; log t, dt, and step index on each failed call; keep one deterministic repro input for local and automated runs.

Anti-Patterns

  1. re-configuring a handle and assuming previous H/IR is still attached
  2. treating tdse_builder_write_pack(...) as proof of semantic correctness
  3. attaching IR without deciding pack representation metadata
  4. debugging Runtime first when Builder snapshots were never captured
  5. letting Runtime compensate for Builder-side source interpretation mistakes
  6. using ad hoc output paths that break pack provenance

Pack Incident Triage

When a pack validation or create issue is reported, collect:

  • Builder configure inputs (dt, nh, np, nq)
  • Builder snapshot from tdse_builder_info(...)
  • whether the pack came from direct H or spectrum conversion
  • any conversion or tail-processing settings
  • whether IR was attached and what pack-form metadata was used
  • result of tdse_pack_validate(...)
  • result and diagnostics from tdse_model_create(...)

If the first five items are missing, do not start by blaming Runtime.