Runs the periodic steady state (.pss) of the circuit in deck, by
shooting–Newton: Newton on the period map x(t0) -> x(t0 + T) with
matrix-free GMRES, the Jacobian products by directional differences
over a frozen-grid replay of the period transient. A linear circuit
converges in one Newton step. The arguments are those of the card
.pss FREQ TSTAB OSCNODE POINTS HARMS SCITER STEADYCOEFF UIC, and
the plots are, value for value, what that card gives in
spice_run() – the same engine call. The deck supplies the circuit
and its .options; its own analysis cards are not run.
Usage
spice_pss(
deck,
freq = 0,
tstab = 0,
osc_node = NULL,
points = 128L,
harmonics = 10L,
max_iter = 50L,
steady_coeff = 1,
uic = FALSE,
includes = NULL,
options = NULL,
tmax_divisor = NULL
)Arguments
- deck
Either the path to a deck file, or the netlist itself as a character vector: a single string containing newlines, or one element per line. A length-one string without a newline is taken as a path. As in SPICE3, the first line of a netlist is its title. A
spice_pic(the extraction of a pic figure,spice_pic()) runs as its netlist, with the.includefiles that came with the figure; one whose diagnostics include an error is refused (spice_error_pic).- freq
The fundamental in Hz;
0(the default) takes it from the periodic sources – the greatest common divisor of their frequencies (SIN/SFFMwith an explicit frequency,PULSE1/PER).- tstab
Stabilization time (s): a plain transient runs to the first multiple of the period at or after
tstab(at least one period) before the shooting starts there.- osc_node
NULLor ngspice's oscillation node. Required for an autonomous oscillator: its phase condition and period estimate (see Details). A driven circuit only checks that it exists.- points
Samples per period, 4 to 10 000 000: the time plot has
points + 1rows, and the period transient steps at mostperiod / points.- harmonics
Rows of the spectrum, the DC included (ngspice's count), 1 to
points %/% 2.- max_iter
Most shooting iterations (at least 1).
- steady_coeff
Scale of the convergence tolerance,
> 0:1(the default) is the SPICE tolerances (reltol,vntol,abstol) on the period mismatch.- uic
Start the stabilization transient from the initial conditions, as
.tran ... uic.- includes
For a netlist given as text only: the files its
.includecards may read, as a named list (or named character vector) mapping the path exactly as written on the card to the file's text. Nothing is read from disk for a text deck. A deck given as a path resolves.includeon the file system, relative to the deck's own directory, and must leaveincludesasNULL; so must aspice_pic.- options
NULLor a named list of simulator options that override the deck's.optionscard, with the card's names and units (temperaturestemp/tnomin degrees Celsius):reltol,abstol,vntol,gmin,itl1,itl2,itl4,gminsteps,srcsteps,temp,tnom,pivtol,pivrel,noopiter,trtol,chgtol,method("trap","gear"or"trbdf2"; unset, a.tranintegrates with"trbdf2"),compat("dune"or"spice3", the 'SPICE3f5' defaults: a trapezoidal.tran, switches flipping on the time grid,ltrabkrate0),ltrabkrate,ltrafit,maxord,nopage,defl,defw,defad,defas,seed(the transient-noise seed, a whole number>= 1; no"random"),notrnoise,devnoise,devnt(the device-noise grid step, seconds,> 0),keepopinfoandtrytocompact. The flagsnoopiter,nopage,ltrafit,notrnoise,devnoiseandkeepopinfotakeTRUE/FALSE(FALSEclears a flag the deck's card set). Unlike a.optionscard, which only warns, an unknown name or a value of the wrong type is an error.- tmax_divisor
As in
spice_run()(it divides the maximum step of the stabilization transient).
Value
A spice_pss, which is also a spice_result (so
spice_plots(), spice_tidy() and spice_measure() on its plots
work as for spice_run()): a list with
title,notes,diagnostics,measurements(always zero rows: a deck's.measurecards do not apply to.pssplots) andplots– the twospice_plots,"Time Domain Periodic Steady State Analysis"and"Frequency Domain Periodic Steady State Analysis"(ngspice's plot names) – as inspice_run();time: one period as a long tibble,points + 1equispaced instants fromt0tot0 + periodper variable:time,variable,type("voltage","current"),value;spectrum: the complex harmonics as a long tibble:harmonic(int, 0 is the DC),frequency,variable,type,re,imand the derivedmag(Mod()) andphase(Arg(), radians). The convention is.ac's phasor:x(t) = X_0 + sum Re(X_k exp(1i * k * w * t)), phases referred tot = 0;magis ngspice's (magnitude-only) plot;period(s: the drive's for a driven circuit, the shooting's result for an oscillator),t0(s, the start of the reported period),residuals: the period mismatchmax_i |x_i(t0+T) - x_i(t0)| / tol_iof each shooting iteration (the last one<= steady_coeff;Inffor an iteration whose transient failed), andperiods: the period of each iteration (constant for a driven circuit, the Newton iterate of an oscillator; the last one isperiod).
Details
The method is Dune's: ngspice-47's .pss is a free-running
oscillator search that detunes from a driving source. points is the
accuracy knob: the error left is the integrator's phase error,
(2 * pi / points)^2 / 12 of the amplitude with the trapezoidal
rule (method = "trap", or compat = "spice3") and about half of
that with the default, TR-BDF2.
A circuit without a periodic source (freq = 0 finds none) is an
autonomous oscillator: the period becomes a Newton unknown, with the
phase pinned where v(osc_node) rises through its mid-range, and is
first estimated by counting the crossings of osc_node over the
second half of tstab (both are required then; a freq given is
only a fallback for fewer than three crossings). The deck must start
the oscillation itself (.ic with uic = TRUE, or a ramp): there is
no automatic kick. The result's periods follows the period per
iteration. A deck with a transient-noise source or with devnoise
on is refused: a random stimulus has no periodic steady state.
Transmission lines take part: the lossless ones (T, and
O in its LC regime) as they are, the lossy RLC/RC lines of O with
options = list(ltrafit = TRUE).
Errors
As spice_run(); a shooting that does not converge in max_iter
iterations is a condition of class spice_error_pss (and
spice_error) whose fields iterations (int) and residuals (dbl)
hold the history, and period (dbl) the last period iterate of an
oscillator (NULL for a driven circuit) – the same condition a
.pss card raises from spice_run(), spice_rerun() and a run of
spice_sweep(). Other failures (an unknown osc_node, an
oscillator without osc_node or tstab, a shooting that settles
on the equilibrium, a transmission line) are spice_error_analysis;
an argument out of range is spice_error_input.
Mirror of the Python package
This is spice.pss(), whose PssConvergenceError is the
spice_error_pss condition here.
See also
spice_run() (a .pss card), spice_measure().
Examples
rc <- "rc low-pass
v1 1 0 sin(0 1 1k)
r1 1 2 1k
c1 2 0 1u
.end"
res <- spice_pss(rc, freq = 1e3, tstab = 2e-3)
res
#> <spice_result> rc low-pass
#> 2 plots:
#> • Time Domain Periodic Steady State Analysis: 4 variables x 129 points, real, scale time
#> • Frequency Domain Periodic Steady State Analysis: 4 variables x 10 points, complex, scale frequency
#> 2 notes:
#> ℹ pss: period 1e-3 s (fundamental 1e3 Hz); shooting over [2e-3, 3e-3] s after 2 stabilization period(s)
#> ℹ pss: 2 shooting iteration(s), residual/tolerance per iteration: 7.754e1, 6.401e-9; 2 adaptive and 2 replayed period transients (GMRES dimensions [1])
#> Periodic steady state: period 0.001 s from t0 = 0.002 s; 2 shooting iterations, residual 6.4e-09.
res$period
#> [1] 0.001
# First harmonic of v(2): |H| = 1 / sqrt(1 + (2 * pi)^2)
subset(res$spectrum, variable == "v(2)" & harmonic == 1)
#> # A tibble: 1 × 8
#> harmonic frequency variable type re im mag phase
#> <int> <dbl> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1000 v(2) voltage -0.155 -0.0247 0.157 -2.98
# The period measures as a transient
spice_measure(res$plots[[1]], "pp v(2)")
#> # A tibble: 1 × 11
#> name analysis plot value trig targ at with from to error
#> <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
#> 1 measure tran Time Domain … 0.314 NA NA NA NA 0 0 NA
# A shooting cut short keeps its history on the condition
e <- tryCatch(spice_pss(rc, freq = 1e3, max_iter = 1), spice_error_pss = identity)
e$residuals
#> [1] 186.2696