Skip to contents

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 .include files 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/SFFM with an explicit frequency, PULSE 1/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

NULL or 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 + 1 rows, and the period transient steps at most period / 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 .include cards 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 .include on the file system, relative to the deck's own directory, and must leave includes as NULL; so must a spice_pic.

options

NULL or a named list of simulator options that override the deck's .options card, with the card's names and units (temperatures temp/tnom in 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 .tran integrates with "trbdf2"), compat ("dune" or "spice3", the 'SPICE3f5' defaults: a trapezoidal .tran, switches flipping on the time grid, ltrabkrate 0), 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), keepopinfo and trytocompact. The flags noopiter, nopage, ltrafit, notrnoise, devnoise and keepopinfo take TRUE/FALSE (FALSE clears a flag the deck's card set). Unlike a .options card, 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 .measure cards do not apply to .pss plots) and plots – the two spice_plots, "Time Domain Periodic Steady State Analysis" and "Frequency Domain Periodic Steady State Analysis" (ngspice's plot names) – as in spice_run();

  • time: one period as a long tibble, points + 1 equispaced instants from t0 to t0 + period per 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, im and the derived mag (Mod()) and phase (Arg(), radians). The convention is .ac's phasor: x(t) = X_0 + sum Re(X_k exp(1i * k * w * t)), phases referred to t = 0; mag is 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 mismatch max_i |x_i(t0+T) - x_i(t0)| / tol_i of each shooting iteration (the last one <= steady_coeff; Inf for an iteration whose transient failed), and periods: the period of each iteration (constant for a driven circuit, the Newton iterate of an oscillator; the last one is period).

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

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