Networks, and how a solve is checked

The answer that is perfect and absurd

A network with a wire written into it as a small resistance returns the right node voltage to fifteen figures, passes both verifications with a residual of two parts in ten to the sixteenth, and reports two hundred thousand amperes. The solver refuses it one decade further on, and by then it has been answering for eight decades.

Assumes: What a network answers, and how the answer is checked

A solver that always returns a number is not a solver; it is a formatter. Half the value of putting a circuit into a matrix is that some circuits have no answer, and the interesting engineering question is what happens at the boundary — not to the ones that are plainly impossible, which are easy, but to the ones a decade away from impossible, which are answered.

A network the solver will answer, and should not be asked, into 0.01 Ω. computed by solving, not by drawing at 61 spreads. A hundredth of an ohm either side of a wire whose resistance is made smaller and smaller, into 0.01 Ω — an element written where the right answer is no element at all. The solution stays exact: 0.499999998422607 at the last spread before the refusal, against 0.500000000000000. What grows is the current-law residual, as the 0.96 power of the spread. The solve is refused at a spread of 2.5e+8, where the smallest pivot falls under 1e-12; the residual tolerance of 1e-7 would have been reached at about 3.3e+9. Two guards written for unrelated reasons, arriving within a decade of one another.
Fig. 1 One network, made steadily worse. A hundredth of an ohm either side of a wire whose resistance is made smaller and smaller, and what is plotted is not the answer — the answer stays exact — but the current-law residual, which grows in proportion to the spread of the matrix until the solve is refused outright.

Four networks with no answer

There are exactly four ways a netlist here fails to determine its own node voltages, and the solver names each of them rather than reporting that a matrix was singular.

A node with no conducting path to the reference. A source, a capacitor, and a resistor going nowhere: the node between the capacitor and the resistor has a potential nothing fixes. The refusal says so — node “x” has no direct-current path to ground, so its potential is not fixed by the network — and it adds the sentence that makes it useful, which is that at zero frequency a capacitor is not a conducting path.

A loop of ideal voltage sources. Two sources across the same pair of nodes. If they disagree the network is contradictory; if they agree it is redundant; and in neither case are the currents in the loop determined by anything. The refusal names the second source and says which loop it closed.

An element with no law of its own. A resistance of zero is not a small resistance. It is a constraint between two nodes — those two potentials are equal — and a constraint is a different kind of object from an element with a current–voltage relation. Stamping it as an admittance of infinity is how a matrix acquires a row of nonsense, so the value is refused where it is given rather than where it does damage.

And the generic case, which is what is left. Two inductors in parallel across a source are three constraints on two unknowns at direct current, and no rule about capacitors or voltage loops catches it. That one comes back as a singular matrix with the smallest pivot quoted, because there is nothing more specific to say.

Four networks the solver refuses. Each has no answer, for a reason that is a fact about the circuit rather than about the arithmetic. The solver names the reason; it does not return a number.
Fig. 2 The first three, drawn as circuits with the refusal each produces underneath. The value of a refusal is that it is a fact about the circuit — a node nothing fixes, a loop whose currents are not determined — rather than a fact about the arithmetic that met it.

Singularity is a property of the netlist and the frequency

The first of those four is worth a second look, because it is the only one that is not permanent.

The netlist with the capacitor in series is refused at direct current. Ask the same netlist for its behaviour at a kilohertz and it solves without complaint, because at s=jωs = j\omega the capacitor is an admittance of jωCj\omega C and every node has a path to the reference through it. The refusal was never about the topology; it was about the topology at zero frequency.

That is worth stating plainly because it is the mechanism behind a whole family of confusing simulator errors. A netlist that will not find an operating point and then runs happily in the frequency domain is not a broken simulator. It is a circuit whose direct-current behaviour genuinely is not determined, being asked a question it has an answer to.

A network the solver will answer, and should not be asked, into 1 Ω. computed by solving, not by drawing at 61 spreads. A hundredth of an ohm either side of a wire whose resistance is made smaller and smaller, into 1 Ω — an element written where the right answer is no element at all. The solution stays exact: 0.990099009899436 at the last spread before the refusal, against 0.990099009900990. What grows is the current-law residual, as the 0.98 power of the spread. The solve is refused at a spread of 1.0e+10, where the smallest pivot falls under 1e-12; the residual tolerance of 1e-7 would have been reached at about 3.8e+7. Two guards written for unrelated reasons, arriving within a decade of one another.
Fig. 3 The same construction into an ohm rather than a hundredth of one, so the divider settles on 0.990099 rather than a half. Everything else is unchanged: the residual still grows in proportion to the spread, the solve is still refused when the smallest pivot goes under tolerance, and the last answer before the refusal is still right to fifteen figures. The exactness is not an artefact of a symmetrical network.

The dangerous case is the one next door

Two ideal sources — five volts and three volts — joined by a resistance. That is the second refusal above with the short replaced by something. Watch what happens as the something shrinks.

joining resistance current returned current-law residual energy check
1 kΩ 2.000000 mA 0 1.2×10161.2\times10^{-16}
1 Ω 2.000000 A 5.0×10165.0\times10^{-16} 1.1×10151.1\times10^{-15}
1 mΩ 2.000000 kA 2.3×10162.3\times10^{-16} 1.1×10161.1\times10^{-16}
10 µΩ 200.0000 kA 3.1×10163.1\times10^{-16} 4.4×10164.4\times10^{-16}
1 µΩ refused

At ten microhms the solver returns two hundred thousand amperes and four hundred kilowatts of dissipation. Both of this site’s standing verifications pass with room to spare — the branch currents sum at every node to three parts in 101610^{16}, and the resistors’ i2R|i|^2R matches the sources’ delivery to four. The answer is not approximately right; it is right. Two ideal sources two volts apart, joined by ten microhms, carry two hundred kiloamps.

Nothing in the netlist is wrong. What is wrong is that nobody has ever built two ideal sources.

A network solved, and checked: a bridge, which no series-parallel reduction reaches. Node 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.
Fig. 4 The two verifications that pass. Both ask whether the solution is consistent with the netlist, and both are satisfied by the answer above — because it is consistent with the netlist. Neither of them, and nothing else on this site, asks whether the netlist is consistent with a circuit.

What actually degrades, and it is not the answer

The natural expectation is that a nearly singular system gives progressively worse answers until it gives up. That is not what happens.

The figure at the top of this essay is a different network — a hundredth of an ohm to a node, a “wire” to a second node, a hundredth of an ohm to ground — with the wire’s resistance swept over twelve decades. The port voltage should be exactly a half once the wire is negligible, and it is:

spread of the matrix node voltage current-law residual
10010^0 0.333333333333333 2.1×10162.1\times10^{-16}
10210^2 0.497512437810945 6.7×10156.7\times10^{-15}
10410^4 0.499975001249938 5.4×10135.4\times10^{-13}
10610^6 0.499999750000125 1.6×10111.6\times10^{-11}
10810^8 0.499999997500000 1.0×1081.0\times10^{-8}
2.5×1082.5\times10^8 0.499999998422607
10910^9 refused

The voltage is right to fifteen figures at the last spread before the refusal. The solve does not decay gracefully; it is exact and then it is absent. What grows meanwhile is the residual, as the 0.96 power of the spread — a slope of one, within what a twelve-decade fit can resolve — and it reaches 10810^{-8} by the time the pivot check stops the solve.

Two guards, written for unrelated reasons

This site has two independent things that could stop the sweep above, and they were put in for completely different reasons.

verifySolution refuses any solution whose worst node-current sum exceeds 10710^{-7} of the largest branch current. That is a statement about Kirchhoff: it says the returned voltages and currents must be consistent with the element laws to a stated fraction, and it was written to catch a wrongly stamped element.

solveAt refuses any matrix whose smallest pivot falls below 101210^{-12} of the matrix norm. That is a statement about Gaussian elimination: it says a factorisation whose pivots have collapsed is not returning a solution but a ratio of rounding errors, and it was written to make the four refusals above come out as refusals rather than as enormous numbers.

They are not related. One is about physics and one is about arithmetic, and neither was written with the other in view. On this network the pivot check fires at a spread of 2.5×1082.5\times10^8, and extrapolating the residual’s fitted slope says the current-law tolerance would have been reached at about 3×1093\times10^9. A decade apart. That is a coincidence, and it is the kind of coincidence worth writing down, because it means the two guards are measuring the same underlying thing from opposite ends: how much of the double’s precision the spread of the matrix has eaten.

A network the solver will answer, and should not be asked, into 0.001 Ω. computed by solving, not by drawing at 61 spreads. A hundredth of an ohm either side of a wire whose resistance is made smaller and smaller, into 0.001 Ω — an element written where the right answer is no element at all. The solution stays exact: 0.0909090900826446 at the last spread before the refusal, against 0.0909090909090909. What grows is the current-law residual, as the 1.02 power of the spread. The solve is refused at a spread of 1.6e+8, where the smallest pivot falls under 1e-12; the residual tolerance of 1e-7 would have been reached at about 6.6e+9. Two guards written for unrelated reasons, arriving within a decade of one another.
Fig. 5 A milliohm load, where the right answer is 0.0909090909… The last solve before the refusal returns 0.0909090900826446 — nine figures, not fifteen, and the difference is the residual having grown to where it can be seen in the answer rather than only in the check. This is the one setting on the page where the two guards disagree about which side of the line the network is on.

The repair the physics already had

Every number in the table above came from a netlist with two ideal sources in it. Put the thing that was left out back, and the whole difficulty disappears — not because the arithmetic improves, but because the question changes into one that has an answer.

Give each source half an ohm of internal resistance, which is what a nine-volt battery has, and join them through a milliohm. The current is 1.996 A, and it is 1.996 rather than 2.000 because two volts across one ohm of internal resistance is two amps and the milliohm of wire takes a fifth of a per cent of it. Shrink the wire to a microhm and the current becomes 1.998 A. Shrink it to nothing and the solve is refused — and by then it does not matter, because the answer has already converged to a number set by the sources rather than by the wire.

internal resistance joining wire current port voltage
0.5 Ω each 1 mΩ 1.9960040 A 3.9999980 V
0.5 Ω each 1 µΩ 1.9979985 A 3.9990012 V
0.05 Ω each 1 mΩ 19.799995 A 4.0097998 V
0.05 Ω each 1 µΩ 19.997800 A 3.9999100 V

Two things worth taking from that. The current between two paralleled supplies is set by their own output impedances, not by the wire between them, which is why the answer stops moving as the wire shrinks. And the singularity was never an arithmetic problem: it was the netlist saying, in the only vocabulary it has, that a quantity had been left out of the model — and the quantity that was left out is the one the answer turns out to depend on entirely.

That is the general shape of it. A singular matrix is usually a missing element rather than a broken solve, and the element it is missing is often the one the interesting number depends on.

Why “stamp it as a milliohm” is the wrong repair

The instinct on meeting any of the four refusals is to nudge the offending element until the matrix inverts. Put a gigohm from the floating node to ground; make the zero-ohm resistor a milliohm; give the two parallel inductors slightly different values.

Sometimes that is right, and it is right for a reason: the real circuit has a leakage resistance, the real wire has a milliohm, and writing it down is modelling rather than fudging. What makes it right is that the number is a property of the thing being modelled.

It goes wrong when the number is chosen to make the matrix work. Then it is unconstrained, and the usual choice — as small as possible, so as not to disturb anything — is exactly the choice that puts the spread of the matrix as close to the cliff as it can get. A milliohm beside a hundredth of an ohm is a spread of ten and is harmless. A nano-ohm beside the same hundredth is a spread of 10710^7, and the residual there is 6×10106\times10^{-10}: still passing, five decades worse than it needs to be, and no longer telling anybody anything if something else in the circuit later goes wrong.

A network the solver will answer, and should not be asked, into 100 Ω. computed by solving, not by drawing at 61 spreads. A hundredth of an ohm either side of a wire whose resistance is made smaller and smaller, into 100 Ω — an element written where the right answer is no element at all. The solution stays exact: 0.999899912362272 at the last spread before the refusal, against 0.999900009999000. What grows is the current-law residual, as the 0.99 power of the spread. The solve is refused at a spread of 1.0e+10, where the smallest pivot falls under 1e-12; the residual tolerance of 1e-7 would have been reached at about 8.7e+4. Two guards written for unrelated reasons, arriving within a decade of one another.
Fig. 6 A hundred ohms, four decades the other way: the divider settles on 0.9999000 and the last good solve returns 0.999899912362272. The spread at which the refusal arrives has barely moved across four decades of load, because what the pivot is small relative to is the largest conductance in the matrix, and that is set by the vanishing wire and not by anything else in the circuit.
A network the solver will answer, and should not be asked, into 0.00001 Ω. computed by solving, not by drawing at 61 spreads. A hundredth of an ohm either side of a wire whose resistance is made smaller and smaller, into 0.00001 Ω — an element written where the right answer is no element at all. The solution stays exact: 0.000999000989020969 at the last spread before the refusal, against 0.000999000999000999. What grows is the current-law residual, as the 0.91 power of the spread. The solve is refused at a spread of 1.6e+8, where the smallest pivot falls under 1e-12; the residual tolerance of 1e-7 would have been reached at about 7.9e+12. Two guards written for unrelated reasons, arriving within a decade of one another.
Fig. 7 And ten microhms, the extreme of the family: the answer is 0.000999000989020969 against an exact 0.000999000999001, and the network is a thousandth of a volt read off a matrix spanning ten decades. Across the five loads this page has drawn — 10 µΩ to 100 Ω, seven decades — the answer is exact until it is absent at every one of them. What changes is only how many figures of it survive the last decade before the refusal.

The rule this leaves

Three sentences, and they are the whole of what the sweep is for.

A refusal is information. Four of them here name a fact about the circuit — a floating node, a source loop, an element with no law, a set of constraints that does not determine the unknowns — and each is more useful than the number it declined to return.

An answer is not evidence that a question was sensible. Every check on this site asks whether the solution is consistent with the netlist. Two hundred kiloamps is consistent with the netlist.

And a spread is a quantity worth looking at. The ratio of the largest conductance in the matrix to the smallest is one number, it is cheap to compute, and it says how much of the precision has already been spent before any answer is asked for. Nothing on this site prints it, which is a gap rather than a decision: every figure here would report a spread in the single digits, and the one network that would report a large one is the one this essay had to construct on purpose.

The reason it is worth the attention anyway is that the failure it produces is silent in the way this collection keeps finding. A wrong element value shows up as a wrong curve. A missing element shows up as a refusal, loudly, at the point of the solve. But an element written where a constraint belonged shows up as an answer that is correct, verified, and about a circuit nobody has: the symptom is not an error but a number, and the only thing that distinguishes it is a reader looking at two hundred kiloamps and knowing that no such current exists.

A 9 V source with 500 mΩ inside it. The ideal source is the flat line. The solved terminal voltage leaves it at a rate set entirely by the internal resistance: 1% low at 180 mA, half gone at 9.0 A.
Fig. 8 Where the whole problem starts. An ideal source is the model that makes the four refusals possible: it is the only element here that fixes a voltage without regard to the current, and every one of the failures above is two such constraints meeting.

Where the refusal is met again

A network the solver will answer and should not be asked is one of three places this field meets the same distinction. The matrix that is ill, and the answer that is not is where a condition number is shown to bound an error rather than predict one. The digits the arithmetic did not have is the same measurement read as a loss of significance. The source that is not a source is the model that makes the refusal necessary, and Exact outside and wrong within is where an ideal source is produced deliberately by a reduction.

The gate

Every refusal is executed rather than described. The four networks are solved in the check, the exception is caught, and its kind is asserted — so a refusal that stopped refusing would fail the build rather than quietly becoming a number.

The sweep is asserted to answer a long way in. Forty-two of sixty-one spreads solve, the last of them returning 0.499999998422607 against a half, and the assertion is on the voltage rather than on the residual: the claim being tested is that the answer stays right, which is the surprising half.

The residual’s growth is fitted rather than asserted flat. 0.96 over the middle of the sweep, measured between 10310^3 and 10810^8 where it is neither on the rounding floor nor near the refusal.

And the same netlist is required to solve at a frequency where it is refused at direct current, which is what keeps “singular” from being read as a property of a topology.

Where the refusal is the right answer, and where it is not

A solver that declines is only useful if it declines for the right reason, and this collection has three cases that between them mark out where the line is.

The matrix that is ill, and the answer that is not is the case where a refusal would have been wrong: a bridge walked towards balance loses one digit per decade of imbalance and has none left at a part in 101510^{15}, on a matrix whose condition number never moves and whose smallest pivot stays four orders above the threshold this solver refuses at. Nothing about the matrix says the answer is worthless — the loss is in the subtraction that produced it — so any refusal keyed on a pivot would have let it through, and did.

The digits the arithmetic did not have is the experiment that tells the two apart, and it is the only one that does: add digits and see. An ill-conditioned problem stays ill-conditioned however many are used and a well-conditioned one computed badly gets better. Its verdict on the bridge is that the loss is entirely the arithmetic’s, and on the ladder synthesis that it is mostly the data’s — two failures that look identical from inside a single run.

And the refusal, and what it was protecting is the case from the semiconductors field where a refusal turned out to be placed conservatively: a current mirror’s model declined below two hundred millivolts of collector-emitter voltage, and putting the missing junction in showed the model still right to seven parts in ten thousand there. A refusal in the wrong place costs answers that were available; a refusal in the right place costs nothing and prevents a plausible wrong one.

Which is the shape of the rule this essay leaves. Refuse on the modelling question — is there a path to ground, is this element a stand-in for something with no value — rather than on a numerical symptom, because a numerical symptom arrives eight decades after the answer stopped meaning anything.

The two hundred thousand amperes, and why nothing objected

The number that gives this essay its title is worth one more look, because the reason no check caught it is a fact about the checks rather than about the network.

What a network answers sets out the two verifications every answer on this site passes: the current law rebuilt from the element laws and summed at every node, and an energy balance computed by a route that reads no resistance. Two hundred thousand amperes satisfies both. The currents do sum at every node, because the solve is exact; the energy does balance, because the power delivered really is the power dissipated in the model as written. What is wrong is not the solution but the netlist, and neither check reads the netlist.

That is the same gap the singular case sits in from the other side. A node with no path to ground is refused because the matrix says so; a node connected through a milliohm that was meant to be a wire is answered, because the matrix is fine. The difference between the two is entirely a modelling intention, and an intention is the one thing a solver has no access to.

Which leaves the practical rule as a habit rather than as machinery. Every element in a netlist should be there because somebody meant it to be an element — and a resistance standing in for the absence of a resistance is the one construction that guarantees an answer nobody can check. The direct voltage that is a sawtooth is the worked example of taking that seriously: faced with a bridge rectifier whose alternating-current nodes float between conductions, it changes the topology to a centre tap rather than adding a large resistor to keep the matrix invertible. The two circuits rectify identically and only one of them is solvable at every step.

What links here

Essays that reach for this one mid-argument — the half of a link its own author cannot write down, the 8 sharing most with it of 16.

What this makes readable

Essays that name this one as a prerequisite.

The objects named here

The third axis, after the field and the idea: the things themselves, and every essay that touches each one.

Kirchhoffs current lawModel refusalModified nodal analysisNumerical errorSingular matrixVerification