DC Operating Point

The DC operating point is the answer to the most basic question a circuit simulator can ask: if nothing is changing, what are all the voltages and currents?

Turn off every time-varying source. Remove every signal. Let the circuit settle into its steady state. The voltages and currents you find there are the DC operating point — and nearly everything else SPICE does (transient analysis, AC analysis, noise analysis) starts from it.

For a circuit with only resistors and voltage sources, finding the operating point is straightforward: assemble the MNA matrix from Chapter 2, solve it, done. One linear system, one solution.

But real circuits have diodes and transistors. These devices are nonlinear — their relationship between voltage and current isn't a straight line. The matrix coefficients depend on the very voltages we're trying to find, which means we can't just solve the system in one step. We need to iterate.

This chapter introduces the algorithm that makes it work: Newton-Raphson iteration. It is the beating heart of every SPICE simulator.


Linear circuits

Consider a resistive voltage divider — three resistors and a voltage source. For a circuit with only linear components, the DC operating point is trivial: stamp once, factor once, solve once.

Four nodes: a, b, c, gnd. The voltage at a is fixed at V by V1. From Chapter 2, each resistor stamps a conductance pattern; the voltage source adds a constraint equation. Assembling everything:

This is a standard linear system: . The matrix contains only constants — resistor conductances and voltage source stamps. The right-hand side is also constant. One call to the sparse solver and we have the answer.

The key property is linearity: the conductance of every component is fixed, independent of the voltages across it. A 2k resistor is always a 2k resistor, whether it has 1V across it or 100V. The matrix can be assembled once and solved once. No iteration, no guessing.

In spice-rs, the ni_iter loop (the Newton-Raphson loop in solver.rs) still runs, but it converges in a single iteration — the first solution is exact, so the convergence check immediately passes.


Nonlinear circuits

Now add a diode to the circuit:

The diode D1 connects node b to ground. Its current is given by the Shockley equation (Chapter 4 covers this in detail):

where A is the saturation current, is the emission coefficient, and mV is the thermal voltage.

The MNA equation at node b is KCL — current in through R1 equals current out through D1:

This is no longer a linear equation. The right-hand side contains — an exponential function of the unknown . There is no way to write this as a matrix entry times .

The circular dependency

For the resistive divider, we could fill in every matrix entry before solving. Not anymore. The diode's contribution to the matrix — its equivalent conductance — is:

This is the slope of the I-V curve at the operating point. But to compute , we need to know — which is the thing we're solving for.

We're stuck in a loop:

This is the fundamental challenge of nonlinear circuit simulation. Every nonlinear device — diodes, MOSFETs, BJTs — creates the same circular dependency.

The solution: don't try to get it right in one step. Iterate.

The Nonlinear Transfer Curve

Before we see how Newton-Raphson solves this, let's visualize what the nonlinear equation looks like. Sweep from 0 to some maximum and plot the diode voltage at each point. This is the transfer curve of the diode-resistor circuit — the function that the simulator must evaluate at every operating point.

The transfer curve reveals the nonlinearity. At low , the diode is off and — the curve follows the dashed linear reference. Once exceeds about 0.6V, the diode turns on and clamps near 0.65V. Beyond that, barely changes no matter how much increases — almost all the additional voltage drops across the resistor.

The sharp bend in the curve is the nonlinearity that Newton-Raphson must handle. A linear solver would predict the dashed line. The iterative solver finds the copper curve by repeatedly linearizing the exponential at each operating point until the solution converges.

Try increasing R — the transition becomes slightly sharper because a larger resistor means less current at the same , and the diode voltage is more sensitive to small current changes near turn-on.


Newton-Raphson iteration

Newton-Raphson is the algorithm that turns a nonlinear problem into a sequence of linear ones. The idea: at each step, linearize every nonlinear device around the current guess, solve the resulting linear system, and use the solution as the next guess. Repeat until the guess stops changing.

The algorithm

  1. Start with a guess for all node voltages (typically 0V, or a smarter initial estimate)
  2. Linearize every nonlinear device at the current guess — replace each device with a conductance and current source that match the device's behavior at that operating point
  3. Stamp the linearized models into the MNA matrix
  4. Solve the linear system to get new node voltages
  5. Check convergence — if the new voltages are close enough to the old ones, stop
  6. Otherwise, go back to step 2 with the new voltages as the guess

Each pass through this loop is called a Newton-Raphson iteration (or just an "NR iteration"). Typical circuits converge in 5-15 iterations.

Linearization: the companion model

At each iteration, the diode is replaced by its companion model — a linear circuit that behaves identically to the diode at the current operating point.

Given a guess at iteration , evaluate the Shockley equation to get the current and its derivative (the small-signal conductance) . The linearized diode is a conductance in parallel with a current source :

This is the tangent-line approximation to the I-V curve. It stamps into the matrix exactly like a resistor (conductance ) plus a current source ().

Interactive NR convergence

Adjust the initial guess below to see how Newton-Raphson converges for the diode-resistor circuit. The table shows the iteration-by-iteration convergence from your chosen starting point.

Try different initial guesses. Notice how starting at 0V takes a big first step (the diode is essentially open), but voltage limiting prevents the exponential from overflowing. Starting near the true solution (~0.65V) converges in just 2-3 iterations — that's the quadratic convergence kicking in.

Quadratic convergence

Newton-Raphson has a remarkable property: once you're close to the answer, the number of correct digits roughly doubles with each iteration. If iteration is off by , iteration is off by about , and by about .

This is called quadratic convergence, and it's why NR is so effective — once the iterates enter the "convergence basin" around the true solution, they converge extremely fast. The challenge is getting close enough for this rapid convergence to kick in.

How spice-rs implements this

The NR loop lives in solver.rs, in the function ni_iter — a faithful port of ngspice's NIiter. Here is the core structure:

loop {
    // 1. Clear matrix and RHS
    sim.mna.clear();

    // 2. Load all devices — each one linearizes at current guess
    //    and stamps its companion model into the matrix
    for device in &mut circuit.devices {
        device.load(&mut sim.mna, ...)?;
    }

    // 3. Add diagonal gmin for numerical stability
    sim.mna.add_diag_gmin(sim.diag_gmin);

    // 4. Factor and solve the linear system
    sim.mna.solve()?;

    // 5. Check convergence — compare new solution to old
    if sim.noncon == 0 && sim.iter_count > 1 {
        sim.noncon = ni_conv_test(sim, circuit, config);
    }

    // 6. If converged, return; otherwise swap and iterate
    if sim.noncon == 0 {
        return Ok(sim.iter_count);
    }
    sim.mna.swap_rhs();
}

Each device's load() function is where linearization happens. The convergence test in ni_conv_test compares every node voltage and branch current between the current and previous solution:

where reltol = and vntol = V by default.


Convergence

Newton-Raphson doesn't always work. The quadratic convergence guarantee holds only when you start close enough to the solution.

What can go wrong

Oscillation. If the I-V curve has regions of very high curvature, Newton-Raphson can overshoot on one iteration and undershoot on the next, bouncing back and forth without settling. The tangent-line approximation is only good locally. Voltage limiting (Chapter 4) directly addresses this.

Slow convergence. Some circuits converge, but painfully slowly — this typically means the circuit has near-singular behavior, with nodes weakly connected to anything.

No solution found. In rare cases, the NR iteration hits the iteration limit (typically 100 or 150 iterations for DC operating point) and gives up.

The convergence test

In spice-rs (ported from ngspice's NIconvTest), convergence is declared when every unknown in the system has stabilized. For each node voltage:

For each branch current:

where the default tolerances are:

The absolute tolerance matters for signals near zero — without it, a node voltage that bounced between and would never "converge" by the relative test alone, even though both values are essentially zero.

In addition to the node-level test, spice-rs (like ngspice) runs a per-device convergence test. Each nonlinear device checks that its terminal voltages haven't changed by more than its own tolerance.

The noncon flag

Inside the NR loop, spice-rs tracks a flag called noncon (short for "non-convergence"). Each device's load() function can set this flag if it applied voltage limiting. The convergence test only runs when noncon is already 0. If any device flagged non-convergence during the load step, the solver skips the test and goes directly to the next iteration.


Gmin and source stepping

When direct Newton-Raphson fails to converge, SPICE doesn't give up. It has fallback strategies that modify the circuit to make it easier to solve, then gradually remove the modifications until the original circuit is recovered.

In spice-rs (ported from ngspice's CKTop), the sequence is:

  1. Try direct Newton-Raphson
  2. If that fails, try dynamic gmin stepping
  3. If that fails, try true gmin stepping
  4. If that fails, try Gillespie source stepping
  5. If everything fails, report "no convergence"

Most circuits converge at step 1. Steps 2-4 are safety nets.

Gmin stepping

Some circuits have nodes that are connected only through nonlinear devices. At the initial guess (all voltages zero), those devices might have nearly zero conductance — meaning the node is effectively floating. A floating node makes the matrix singular or near-singular.

The solution: add a small conductance from every node to ground. This is called gmin — a minimum conductance that ensures no node is ever truly floating.

The trick is to start with a large gmin (around S), solve the circuit, then gradually reduce gmin while using each solution as the starting point for the next:

  1. Set S. Solve. (Easy -- heavy damping.)
  2. Reduce by a factor (typically 10). Solve, using the previous solution as the initial guess.
  3. Repeat until reaches its target value ( S by default).
  4. Do one final solve with gmin at its target. This is the real answer.

Each step only changes the circuit slightly, so Newton-Raphson converges quickly from the previous solution.

Dynamic gmin adds gmin to the matrix diagonal only. The factor between steps adapts based on how many NR iterations the previous step required. True gmin adds gmin as a per-device parameter inside each semiconductor's equations, which is more physically meaningful.

Source stepping

Source stepping takes a different approach: instead of modifying the circuit's connectivity, it modifies the excitation. All independent voltage and current sources are scaled by a factor that ramps from 0 to 1.

With all sources at zero, every node is at 0V and every device is in a well-defined (if boring) state. Then the sources are gradually increased, with the solver tracking the operating point smoothly at each step.

Source stepping is most effective for circuits where the difficulty comes from the magnitude of the excitation rather than the topology.

The big picture

These convergence aids are what make SPICE practical for real circuits. The hierarchy of fallbacks reflects a design philosophy: try the simplest (and fastest) approach first, then progressively deploy heavier tools. Direct NR is fast but fragile. Gmin stepping is slower but more robust. Source stepping is slowest but handles the widest range of circuits.