Summary
In PSpice compatibility mode (ps or ltps), a voltage-controlled switch defined with a PSpice VSWITCH model, which ngspice maps to the XSPICE pswitch code model, returns a physically impossible small-signal AC gain in a purely passive network. A switch biased mid-way between VOFF and VON feeding a 1 kOhm load should give a transfer of 0.5; ngspice reports about 4.6e15. LTspice gives 0.5 for the same circuit.
Version / platform
ngspice-47 release, built from ngspice-47.tar.gz (./configure --without-x --with-readline=no), Linux x86-64. Not yet re-tested against current git master.
Reproducer (two files in the same directory; .spiceinit contains set ngbehavior=ps)
v_switch_signal.cir:
Independent PSpice switch signal transfer
.include "v_switch_signal.lib"
VDR IN 0 DC .1 AC 1
XU IN OUT DEMO
.save all
.ac lin 3 .99 1.01
.meas ac m_re FIND vr(OUT) AT=1
.meas ac m_im FIND vi(OUT) AT=1
.end
v_switch_signal.lib:
.subckt DEMO IN OUT
VCTRL CTRL 0 .1
S1 IN OUT CTRL 0 MODE
.model MODE VSWITCH(RON=100 ROFF=10000 VON=.2 VOFF=0)
R1 OUT 0 1k
.ends DEMO
Run: ngspice -b v_switch_signal.cir
Expected
The control voltage (0.1 V) is half-way between VOFF (0 V) and VON (0.2 V), so the PSpice switch resistance is sqrt(RON*ROFF) = 1 kOhm, a 1k/1k divider: m_re = 0.5, m_im = 0. LTspice 26.1.1 gives m_re = 0.50000000025.
Actual
ngspice-47 in ps and ltps modes: m_re = 4.61169e15, m_im = 0. (Default and lt modes reject the deck.)
Notes
Thanks for the report. Indeed the ac output is buggy.
What has been your solution?
Thanks for confirming it @h_vogt. I've attached a patch against current master (a80f6e3e).
The problem is in the AC branch of the pswitch code model. Its conductance entries use the opposite sign to the DC current Jacobian, and it never stamps the control port's input loading. While checking that, I also found that the derivative in the logarithmic transition region wasn't normalized by the control voltage span, and that the control derivative stays nonzero where the resistance is clamped. aswitch has the same sign error and the same clamping issue, so the patch fixes both models.
To check it without relying on another simulator, I compared each AC result against a numerical derivative of the DC operating point (central differences at two step sizes) on 97 small test circuits. They cover both control directions, linear and log interpolation, the off, transition and on regions, input loading and clamping. 86 of them failed before the patch; all 97 pass after it. A three-switch amplifier with a DC gain of about 2.66e6 shows an AC gain of 0 before the patch and the matching value after.
The patch adds an analog regression test to make check. It fails before the change and passes after. The full suite passes (59 tests), the existing CMC comparison results are unchanged, and the seven examples I tried behave the same.
Here is a minimal case using pswitch directly, with no compatibility mode:
With the control at 0.1 V the switch sits at 1 kΩ, so the expected transfer is 0.5. Unpatched master gives 4.61e15; with the patch it gives 0.5.
One separate thing came up while testing a larger op-amp macromodel. If the DC operating point fails and ngspice falls back to a transient-based operating point, a DC servo loop in the circuit can be left far from equilibrium, and the AC gain is then meaningless. This patch doesn't change that behavior. I mention it in case it's worth a separate ticket.