When the simulator lies
Recognise the runs that return a confident wrong number (missing DC paths, coarse time steps, ideal sources, more than one answer) and fix each one.
- Lesson
- E1.6
- Time
- 25 min
- Runs on
- ngspice
- Check
- 5 questions
A bench drove an ideal 1 mA current source into a node whose only other part was a 1 pF capacitor. The operating point printed v(a) = 9999.95 V, ten kilovolts on a 1.8 V chip. The log had "singular matrix" warnings, the run finished without an error, and the next check used the number.
- Nowhere for the current to go
In an operating point the capacitor is open. Kirchhoff's law at node a says 1 mA = 0, which no voltage satisfies.
1 mA
Read the circuit as text
- I1 current source (1 mA): + →
0, − →a - C1 capacitor (1 pF): pin 1 →
a, pin 2 →0
a= 9999.95 V
The pill is what op printed on ngspice 42.
SPICE does not refuse a circuit that makes no sense: it often returns a number anyway, and the warnings are part of the result.
No DC path: where the number comes from
A node with no DC path is joined to the rest of the circuit only through capacitors or a current source. In an operating point the capacitors are open, so nothing fixes that node's voltage. The equations have no single solution, and ngspice reports a singular matrix.
It does not stop there. It tries gmin stepping, which adds small conductances and removes them step by step, then source stepping, which ramps the sources up from zero. When both fail, it runs a short transient, the transient operating point, and takes its end as the answer.
That transient lasts 10 µs. A 1 mA current into 1 pF for 10 µs charges it to 1 mA × 10 µs / 1 pF = 10 kV. The missing 0.05 V is a leak equal to gmin, the solver's 10−12 S minimum conductance: change gmin and the number moves exactly as that leak predicts. So 9999.95 V describes ngspice's fallback, and none of it describes your circuit.
Run a DC sweep on the same netlist and you get a different answer, va_dc = 1.000000e+09: 1 mA through the gmin conductance alone, 1 GV. Two analyses, two confident numbers, neither real.
| Bench | What the log says | What prints | Fix |
|---|---|---|---|
1 mA into 1 pF, op | singular matrix; gmin and source stepping failed | 9999.95 V | a DC path: R1 a 0 1meg gives 1000 V |
| two 1 nF in series from a 1 V source, middle node | singular matrix; transient op | 0.5000 V | a resistor to a defined voltage |
| NMOS with its gate left open | singular matrix; transient op | gate at 0.5005 V | drive the gate; .options rshunt=1e12 shows 0 V |
| 1 mA and 2 mA current sources in series | nothing at all | v(a) = −1.000 mV | real sources have resistance; add it |
| two voltage sources (1 V and 2 V) in parallel | Timestep too small; op aborted | nothing | one source, or a series resistor |
Each line measured on ngspice 42. Only the last one stops; the other four print a number with no error.
The fix is always the same idea: give every node a DC path to a defined voltage. That can be a bias resistor, a real driver, or the output resistance a real source has. The middle-node voltage of two capacitors, 0.5000 V, looks plausible, which makes it the most dangerous number in the table.
A waveform is samples
tran 2u 100u. Straight lines join the computed points.- Time 56.56 µsv(in) = -830.6 mV
The lowest computed point is −0.8306 V.
meas MINreports it, becausemeasonly sees the points the solver computed. - Time 92.56 µsv(in) = 999.3 mV
The highest point, 0.9993 V, lies close to a crest by luck. Five points per period cannot draw a sine.
Read the plot as a table
| Time | v(in) |
|---|---|
| 0 s | 0 V |
| 20 µs | 27.98 mV |
| 40 µs | 27.98 mV |
| 56.56 µs | -830.6 mV |
| 60 µs | 27.98 mV |
| 80 µs | 27.98 mV |
| 92.56 µs | 999.3 mV |
| 100 µs | -2.449 fV |
Measured on ngspice 42: 59 time points in 100 µs.
A transient result is a list of samples joined by straight lines. Each sample is right: −0.8306 V is the true value of the sine at 56.56 µs. What is missing is the points in between. With tran 2u 100u the solver may step up to 2 µs at a time, which is a fifth of the 10 µs period. The run reports vmin = -8.305959e-01, and nothing in the log warns you.
Ask for a shorter step and the peaks return. tran 10n 100u gives −0.9999985 V and 0.9999985 V. So does keeping the 2 µs print step and capping the internal step with a fourth number, tran 2u 100u 0 10n, which gives ±0.9999968 V. Resolve the fastest thing you care about with ten to twenty points.
Aids that steer, and circuits with two answers
gmin, 10−12 S by default, is also what ngspice places across device junctions to help convergence. It is invisible until a current is as small as gmin times a voltage; E2.6 shows it dominating a transistor's off current.
.nodeset gives the solver a starting guess for some nodes, then releases them, so it cannot change the answer unless the circuit has more than one. .ic is stronger. It holds nodes at the given values while the transient's starting point is solved, then lets go, so the run starts from a state you chose.
A latch, plain op
XP1 q qb vdd vdd sky130_fd_pr__pfet_01v8 W=1 L=0.15
XN1 q qb 0 0 sky130_fd_pr__nfet_01v8 W=0.5 L=0.15
XP2 qb q vdd vdd sky130_fd_pr__pfet_01v8 W=1 L=0.15
XN2 qb q 0 0 sky130_fd_pr__nfet_01v8 W=0.5 L=0.15
op prints v(q) = v(qb) = 0.8819 V, with no warning: the balanced point where neither inverter wins.
The same latch with a guess
.nodeset v(q)=1.8 v(qb)=0
* or the opposite guess:
* .nodeset v(q)=0 v(qb)=1.8
v(q) = 1.8 V and v(qb) = 0.62 µV; the opposite guess gives the opposite state. All three are valid solutions.
Two cross-coupled SKY130 inverters at 1.8 V, measured on ngspice 42.
A latch has two stable states and one balanced, unstable one. op returns whichever one its start leads to, here the balanced one, which a real latch never stays in. E4.5 shows the same trap in a bias reference that the operating point finds working and a power-up transient finds dead.
The rule for every case on this page: read the log, not only the numbers. A run that finishes is not a run that is right.
Asked in interviews
What does "singular matrix" mean in SPICE, and how do you fix it?
The circuit equations have no unique solution, usually because a node has no DC path to ground (only capacitors or current sources) or voltage sources form a loop. Give every node a DC path, add series resistance to ideal sources, and treat any number printed after the warning as meaningless.
Why can a transient waveform miss a peak?
The result is samples at the solver's time points, and measurements only see those points. A step that is long compared with the signal skips the peaks. Shorten tstep or set tmax so the fastest edge or period gets 10-20 points.
Can a circuit have more than one DC operating point?
Yes: latches, flip-flops and self-biased references have several. The operating point returns the one its starting guess leads to. Use .nodeset to pick a state, and a power-up transient to see which one the real circuit reaches.
Try it
Run it and open the log: the singular-matrix warnings, the failed stepping, then the transient operating point. The transient's starting point is 9999.95 V; the DC sweep's point is 1 GV.
Now add R1 a 0 1meg and rerun: both numbers become 1000 V, and the warnings vanish. Then change C1 to 1n without the resistor and predict va_tran from the 10 µs rule.
Run the netlist to draw its plots here.
va_tran = 9.999950e+03 va_dc = 1.000000e+09Check yourself
Remember
- A node with no DC path makes the matrix singular; ngspice falls back to gmin stepping, source stepping and a 10 µs transient, and prints a number anyway.
- Read the log: warnings are part of the result, and a run that finishes is not a run that is right.
- A transient result is samples; MIN, MAX and peaks are only as good as the time step, so cap it with tstep or tmax.
- Ideal sources in impossible combinations either abort or print nonsense; real sources have resistance.
- Some circuits have several DC solutions; op returns one, and .nodeset picks which.