What this is

About this collection

Illustrated essays on electrical networks, built on a solver that computes each circuit and checks its own answer before anything is drawn — and on one rule, that no model appears without the frequency, amplitude or size at which it stops being true.

The rule

Every model in this subject is an approximation with a range. The ideal operational amplifier is exact enough to design with at audio frequencies and useless at ten megahertz. The small-signal transistor is excellent at a millivolt and meaningless at a volt. A capacitor is a capacitor until it is an inductor. Kirchhoff's own laws assume the signal crosses the circuit in no time, which it does not.

None of that is unknown. What is missing almost everywhere is the number: how far the model can be pushed before it costs something, stated as a frequency or an amplitude or a length rather than as a warning. So this collection has one rule, and it governs every figure:

No model is drawn without the frequency, amplitude or size at which it stops being true.

The number goes in the caption strip along the bottom of each figure, in the same place every time, and it is computed from the model's own parameters rather than quoted. A figure whose model has no stated edge would be visibly missing one.

What is underneath

Six libraries, and the first of them is the site. lib/network.js is modified nodal analysis over the complex plane: a netlist goes in, and node voltages and branch currents come out at any complex frequency. Direct current is not a separate theory but the value at zero frequency; a phasor sweep is the same solve along the imaginary axis; a pole is a frequency at which the matrix stops being invertible. One solver, three things usually taught as three subjects.

The solver is complex-valued from its first line. Retrofitting phasors onto a real solver is a rewrite — every stamp, every pivot, every residual changes type — and doing it over the complex numbers from the start costs nothing.

lib/response.js turns a solved network into the things a reader recognises. The poles are not written down symbolically anywhere: the nodal matrix is affine in the complex frequency, so its determinant is a polynomial, so sampling that determinant on a circle in the complex plane and transforming back recovers the polynomial exactly, and its roots are the poles. That matters because it makes a check available — the magnitude computed by inverting the matrix and the magnitude computed from the recovered poles must agree, and they do to about a part in ten to the fifteenth.

lib/devices.js holds the models themselves, each expanded into primitives rather than written as a formula, so that a real amplifier's loading and output impedance are solved rather than assumed away. lib/limits.js is the unusual one: its only job is to compute where the rest of the library stops applying. lib/filter.js computes each filter family's poles from its definition and then builds the network, so the trade-off between them can be measured. And lib/complex.js is the arithmetic underneath all of it.

How a solution is checked

The assembly of a nodal matrix is the part most likely to be wrong and the part least likely to look wrong. A misplaced sign in one element's stamp gives a smooth, plausible Bode plot, and no amount of looking at it will help.

So every solve here is checked twice before it is returned, by routes that do not use the stamps that produced it. First, each branch current is recomputed from that element's own constitutive relation and the currents are summed at every node: Kirchhoff's current law has to hold, and it does, to the last few bits of a double. Second — and deliberately not a restatement of the first, because the current law constrains only the currents — the power dissipated in the resistors is computed as |i|²R without reading a single node voltage, and the power delivered by the sources is computed as Re(v·i*) without reading a single resistance. Those two agree only if the voltages and the currents are consistent with each other.

The refusals

A library that only ever succeeds has not been tested. A network with no conducting path to ground does not have an approximate answer, it has none, and the matrix that describes it is singular. So the solver diagnoses the circuit rather than reporting the arithmetic: it names the floating node, or the loop of ideal voltage sources, or the element given a resistance that is not a resistance. The models do the same — an ideal amplifier asked for its behaviour above its own gain–bandwidth product declines, because its prediction there is not approximate, it is meaningless.

What the figures are

Every picture is a function that solves a circuit and returns SVG. Nothing is drawn by hand and nothing is drawn to look right. Each generator carries assertions about what it has just computed, and those assertions run at build time — a figure whose circuit does not do what its caption says stops the build rather than shipping.

Where a figure has a parameter worth moving, it has a slider, and every frame on that slider was produced at build time by the same generator that drew the static picture. So every assertion has been checked at every position a reader can reach: turning the handle is testing the claim's generality, and the build has already tested it too. With scripting off the figure is the argument and the slider is what is missing, not the other way round.

The schematic is a label

Two drawings of the same circuit with different placement are the same circuit, so a schematic's layout carries no information. That is exactly not true of, say, a mechanism, where the geometry is the content — and it is the reason this site is organised around responses rather than around schematics. Where a circuit needs to be shown, it is drawn small, in one consistent hand, and put in a corner. The canvas belongs to what the circuit does.

What this is not

It is not a simulator. There is an excellent free one, it has been widely loved for years, and building a worse one would be pointless; the gap this collection fills is not simulation but argument, and specifically the measured edge of each model, which no simulator draws.

It is also not a component reference. Anything that depends on what a particular part does this year rots on a revision cycle, so values that stand in for real devices are stated as what they are — round numbers chosen to be representative — and no argument here rests on a version number or a datasheet. And it is not design guidance: it explains, it does not certify.

Reading order

There is none. Each essay is written to stand alone, and the fields exist so that a reader who wants one thread can follow it. The threads cut across the fields and are the more interesting index of the two.

A network solved, and checked: a bridge, which no series-parallel reduction reachesNode potentials from modified nodal analysis. The branch currents are then recomputed from each element's own law and summed at every node; the residual is 2.7e-16 of the largest current in the circuit, which is floating-point rounding and nothing else.a bridge, which no series-parallel reduction reachesnode a7.5566 Vnode b4.7993 Vcurrent law, rebuilt from the element laws2.71e-16 of the largest branch currentpower delivered against power dissipated4.33e-16 apart · 48.07 mWsolved, then checked — 6 elementsa linear network has no edge: this one is exact
Fig. 1 A network solved, with the check printed beside the answer. The node potentials are what the matrix returned; the residual underneath is Kirchhoff’s current law rebuilt from the element laws and summed at every node, which is floating-point rounding and nothing else.