Skip to content

withStamp

withStamp(block, stamp): object

Defined in: packages/compiler/src/couple.ts:473

A new stamp, added to a block whose linear/controlFree are re-derived rather than assumed unchanged — the same rule lowerRegion itself follows, so a stamp this stage adds cannot silently leave a block claiming a solver cost or a control independence its own stamps contradict.

Exported for dangling-active-terminal.ts’s implicit op-amp bias synthesis, which adds a stamp to an already-linked block for the same reason this stage does: a block’s derived fields must never describe a stamps array it does not have.

number

Extra unknowns for voltage sources and op-amp outputs.

boolean

No stamp here reads a control, so this block’s coefficients do not change when a knob moves.

The other half of “may this be factored once at load”. linear alone is not enough and the difference is not bookkeeping: gate 1c measured a state-space realisation derived at one control position and evaluated at another to be wrong by 80% of the signal (4.19e-02 against a 5.23e-02 reference RMS). So a precomputation gated on linear alone would be exact on the fixture that derived it and wrong on the same circuit one knob-turn later.

Also from the stamps, because a control-bearing device need not lower to a control-bearing stamp: a switched jack’s port-engage contact becomes a plain conductance.

boolean

True when symbolic elimination (DK reduction) is admitted for this block. Admitted when the block is nonlinear and the reduction ratio (unknowns / portCount) >= 4.0.

string

number | null

Null when this region does not contain the circuit’s input jack.

"mna"

boolean

No stamp here has to be re-evaluated inside a Newton loop, so the block solves in a single pass. Read by the runtime to choose between one solve and the iteration cap, and derived from the stamps rather than from the region’s device list — see stampNeedsNewton.

Stated positively rather than as nonlinear because it is a licence: the false case costs iterations, and the true case is what later build steps are allowed to exploit. A flag whose safe default is false should read as the thing being claimed.

number

How many node unknowns this block solves. Always nodeIds.length — the two are set together at the single site that builds them (lowerRegion), and this one exists because the runtime reads it in its innermost loops.

readonly number[]

Row index -> the source NodeId that row stands for. nodeIds[0] is always GROUND, because the runtime pins row 0 and starts its gmin loop at 1.

A block’s rows are numbered 0..nodeCount-1, not by the node ids the document authored. They used to be the same thing: the row index was the authored id, so a block’s matrix was sized by the largest node label in its region rather than by how many nodes it has. Two things then inflated it independently — a document numbering a net 900 (jhs-424-gain-stage labels its +10 V rail that, and got a 909-unknown matrix for a 30-node circuit), and a multi-region document, where regions are node-disjoint but each one’s matrix still spanned the global id range up to its own maximum (boss-os-2: 46 regions, the driven one sized 354). Corpus-wide that was 77,062 analog rows where 4,829 nodes exist, and the padding rows carried nothing but gmin.

This array is the inverse map, and it is not optional bookkeeping: several consumers bridge a solved row back to a declared net — the ngspice deck names (scripts/lib/program-to-spice.ts, which must stay in the same namespace as source-to-spice.ts or parity compares two different nodes and still reports agreement), the declared-rail check in report-transistor-bias.ts, and the node labels report-signal-path.ts and render-v2-audio.ts --held print. Use blockNodeIndex for the forward direction.

Every node of every device in the region is kept, including terminals no device law stamps (an op-amp’s vcc/vee). The renumbering is a bijection on the region’s node set, so no node is removed and nothing about what the block models changes.

readonly OperatingPointSeed[]

Where the operating-point solve starts, for nodes whose initial value decides which of several DC solutions the block settles into. Empty for the ordinary case of a circuit with one solution.

number | null

Null when this region does not contain the circuit’s output jack.

SparseSchedule | null

Compile-time static sparse elimination schedule. Derived once at compile time and emitted on the program as data.

StampPartition

Compile-time stamp partition for linear/nonlinear, control, and constant stamps. Derived once at compile time and emitted on the program as data.

readonly Stamp[]

number

Stamp

readonly auxCount: number

Extra unknowns for voltage sources and op-amp outputs.

readonly controlFree: boolean

No stamp here reads a control, so this block’s coefficients do not change when a knob moves.

The other half of “may this be factored once at load”. linear alone is not enough and the difference is not bookkeeping: gate 1c measured a state-space realisation derived at one control position and evaluated at another to be wrong by 80% of the signal (4.19e-02 against a 5.23e-02 reference RMS). So a precomputation gated on linear alone would be exact on the fixture that derived it and wrong on the same circuit one knob-turn later.

Also from the stamps, because a control-bearing device need not lower to a control-bearing stamp: a switched jack’s port-engage contact becomes a plain conductance.

readonly eliminate: boolean

True when symbolic elimination (DK reduction) is admitted for this block. Admitted when the block is nonlinear and the reduction ratio (unknowns / portCount) >= 4.0.

readonly id: string

readonly inputNode: number | null

Null when this region does not contain the circuit’s input jack.

readonly kind: "mna"

readonly linear: boolean

No stamp here has to be re-evaluated inside a Newton loop, so the block solves in a single pass. Read by the runtime to choose between one solve and the iteration cap, and derived from the stamps rather than from the region’s device list — see stampNeedsNewton.

Stated positively rather than as nonlinear because it is a licence: the false case costs iterations, and the true case is what later build steps are allowed to exploit. A flag whose safe default is false should read as the thing being claimed.

readonly nodeCount: number

How many node unknowns this block solves. Always nodeIds.length — the two are set together at the single site that builds them (lowerRegion), and this one exists because the runtime reads it in its innermost loops.

readonly nodeIds: readonly number[]

Row index -> the source NodeId that row stands for. nodeIds[0] is always GROUND, because the runtime pins row 0 and starts its gmin loop at 1.

A block’s rows are numbered 0..nodeCount-1, not by the node ids the document authored. They used to be the same thing: the row index was the authored id, so a block’s matrix was sized by the largest node label in its region rather than by how many nodes it has. Two things then inflated it independently — a document numbering a net 900 (jhs-424-gain-stage labels its +10 V rail that, and got a 909-unknown matrix for a 30-node circuit), and a multi-region document, where regions are node-disjoint but each one’s matrix still spanned the global id range up to its own maximum (boss-os-2: 46 regions, the driven one sized 354). Corpus-wide that was 77,062 analog rows where 4,829 nodes exist, and the padding rows carried nothing but gmin.

This array is the inverse map, and it is not optional bookkeeping: several consumers bridge a solved row back to a declared net — the ngspice deck names (scripts/lib/program-to-spice.ts, which must stay in the same namespace as source-to-spice.ts or parity compares two different nodes and still reports agreement), the declared-rail check in report-transistor-bias.ts, and the node labels report-signal-path.ts and render-v2-audio.ts --held print. Use blockNodeIndex for the forward direction.

Every node of every device in the region is kept, including terminals no device law stamps (an op-amp’s vcc/vee). The renumbering is a bijection on the region’s node set, so no node is removed and nothing about what the block models changes.

readonly operatingPointSeeds: readonly OperatingPointSeed[]

Where the operating-point solve starts, for nodes whose initial value decides which of several DC solutions the block settles into. Empty for the ordinary case of a circuit with one solution.

readonly outputNode: number | null

Null when this region does not contain the circuit’s output jack.

readonly sparseSchedule: SparseSchedule | null

Compile-time static sparse elimination schedule. Derived once at compile time and emitted on the program as data.

readonly stampPartition: StampPartition

Compile-time stamp partition for linear/nonlinear, control, and constant stamps. Derived once at compile time and emitted on the program as data.

readonly stamps: readonly Stamp[]

readonly stateCount: number