Skip to contents

Parses a SPICE3 netlist, builds the circuit and runs every analysis card in deck order, exactly as spice3 -b (and dune -b) would.

Usage

spice_run(deck, 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).

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

NULL (the default) or a finite number >= 1 that divides the maximum step of every .tran card – its TMAX argument, else the default min(TSTEP, (TSTOP - TSTART) / 50). The run is, bit for bit, that of the deck with the card's TMAX edited to TMAX / tmax_divisor; with options = list(trtol = 1) it gives the "fine steps" view of a waveform. It is an argument rather than an options name because TMAX is a parameter of the analysis card, not an engine option.

Value

A spice_result: a list with

  • title: the deck's title line;

  • plots: a named list of spice_plot objects, one per rawfile plot, in the order spice3 -b -r writes them (one for most analyses; .noise adds an integrated-noise plot when the band has more than one frequency; .disto gives two or three). Names are the plot names ("Transient Analysis", ...) made unique with make.unique() when an analysis appears twice;

  • notes: non-fatal remarks from the engine;

  • diagnostics: a tibble (severity, message) of the parser's warnings, each message prefixed with its file:line:col;

  • measurements: the deck's .measure cards (ngspice grammar), each evaluated on every plot of its analysis, as the tibble spice_measure() returns (zero rows without .measure cards). Failed measurements are rows with error set.

Errors

Failures are signalled with cli::cli_abort() as conditions of class spice_error_<kind> and spice_error, where kind is the stage that failed: "options", "io" (unreadable deck file), "parse", "elaborate" (building the circuit), "analysis" or "pss" (a .pss card whose shooting did not converge; see spice_pss() for the condition's iterations and residuals fields) (and, from spice_alter(), "alter"; for a spice_pic with extraction errors, "pic"). Parse errors carry the file:line:col of the offending card in the message; the condition's diagnostics field holds every diagnostic seen so far.

Mirror of the Python package

This is the R face of spice.simulate() in the Python package of the same name. Both run the same engine with the same semantics; the R side returns S3 objects and long tibbles where Python returns polars frames.

A long simulation cannot be interrupted from R: the call returns when the engine finishes.

Examples

deck <- "rc low-pass
vin 1 0 pulse(0 1)
r1 1 2 1k
c1 2 0 1u
.tran 0.1m 5m
.end"
res <- spice_run(deck)
res
#> <spice_result> rc low-pass
#> 1 plot:
#> • Transient Analysis: 4 variables x 63 points, real, scale time
head(spice_tidy(res))
#> # A tibble: 6 × 7
#>   plot               point scale_name    scale variable type    value
#>   <chr>              <int> <chr>         <dbl> <chr>    <chr>   <dbl>
#> 1 Transient Analysis     1 time       0        v(1)     voltage  0   
#> 2 Transient Analysis     2 time       0.000001 v(1)     voltage  0.01
#> 3 Transient Analysis     3 time       0.000002 v(1)     voltage  0.02
#> 4 Transient Analysis     4 time       0.000004 v(1)     voltage  0.04
#> 5 Transient Analysis     5 time       0.000008 v(1)     voltage  0.08
#> 6 Transient Analysis     6 time       0.000016 v(1)     voltage  0.16

# Options override the deck's .options card
spice_run(deck, options = list(reltol = 1e-4, method = "gear"))
#> <spice_result> rc low-pass
#> 1 plot:
#> • Transient Analysis: 4 variables x 70 points, real, scale time

# Finer transient steps: trtol = 1 and a tenth of the maximum step
spice_run(deck, options = list(trtol = 1), tmax_divisor = 10)
#> <spice_result> rc low-pass
#> 1 plot:
#> • Transient Analysis: 4 variables x 508 points, real, scale time