API Reference

spice-rs can be used in three ways:

  1. Rust library -- direct integration via spice_rs crate
  2. WebAssembly module -- browser and Node.js usage via spice-rs-wasm
  3. sparse-rs -- standalone sparse matrix solver (KLU and Markowitz backends)

All three share the same simulation core. The WASM module wraps the Rust API with JSON serialization. sparse-rs is an independent crate that can be used without the SPICE engine.


Rust API

Add spice-rs as a dependency:

[dependencies]
spice-rs = { path = "../sim/spice-rs" }

High-level runner functions

All runner functions accept a netlist string and return a Result.

run_netlist

pub fn run_netlist(netlist: &str) -> Result<(HashMap<String, f64>, Analysis), String>

Runs whatever analysis the netlist specifies (.OP, .TRAN, .AC, .DC, .SENS, .TF, .PZ). Returns node voltages/branch currents as a HashMap, plus an Analysis enum indicating which analysis ran.

For .TRAN, the returned HashMap contains the values at the last timepoint.

run_netlist_tran_waveform

pub fn run_netlist_tran_waveform(netlist: &str)
    -> Result<(Vec<String>, TransientResult), String>

Runs transient analysis and returns full waveforms. TransientResult has:

run_netlist_dc_sweep

pub fn run_netlist_dc_sweep(netlist: &str) -> Result<DcSweepWaveform, String>

Runs a .DC sweep analysis. DcSweepWaveform has:

run_netlist_ac

pub fn run_netlist_ac(netlist: &str) -> Result<AcWaveform, String>

Runs .AC analysis. AcWaveform has:

run_netlist_params

pub fn run_netlist_params(netlist: &str)
    -> Result<Vec<(String, Vec<(String, f64)>)>, String>

Returns device operating-point parameters after DC analysis.

run_netlist_dc_op_profiled

pub fn run_netlist_dc_op_profiled(netlist: &str)
    -> Result<(HashMap<String, f64>, Vec<NrSnapshot>), String>

Runs DC operating point and returns NR iteration snapshots for debugging convergence.

Complete example

use spice_rs::runner::run_netlist;

fn main() {
    let netlist = "\
Voltage Divider
V1 vdd 0 DC 3.3
R1 vdd mid 10K
R2 mid 0 10K
.OP
.END
";

    match run_netlist(netlist) {
        Ok((voltages, _analysis)) => {
            for (node, value) in &voltages {
                println!("{}: {:.4} V", node, value);
            }
        }
        Err(e) => eprintln!("Simulation error: {}", e),
    }
}

Transient example

use spice_rs::runner::run_netlist_tran_waveform;

fn main() {
    let netlist = "\
RC Step Response
V1 in 0 PULSE(0 1 0 1N 1N 10U 20U)
R1 in out 1K
C1 out 0 1N
.TRAN 10N 20U
.END
";

    let (names, result) = run_netlist_tran_waveform(netlist).unwrap();
    println!("Signals: {:?}", names);
    println!("Timepoints: {}", result.times.len());
    println!("Accepted: {}, Rejected: {}", result.accepted, result.rejected);
}

WASM API

The spice-rs-wasm package exposes spice-rs to JavaScript via WebAssembly. It works in browsers and Node.js.

Installation

Build from source with wasm-pack:

cd sim/spice-rs-wasm
wasm-pack build --target web

This produces a pkg/ directory with .wasm, .js, and .d.ts files.

SimulationEngine

All methods accept a SPICE netlist string and return a JSON string.

Constructor

dc_op(netlist) -> string

Runs DC operating point analysis. Returns:

{
  "nodes": { "vdd": 3.3, "mid": 1.65 }
}

tran(netlist) -> string

Runs transient analysis with full waveforms. Returns:

{
  "times": [0.0, 1e-9, 2e-9],
  "signals": { "v(out)": [0.0, 0.001, 0.003] },
  "names": ["v(out)", "v(in)"],
  "accepted": 1234,
  "rejected": 56
}

dc_sweep(netlist) -> string

Runs DC parameter sweep.

ac(netlist) -> string

Runs AC frequency sweep. Returns real/imaginary parts plus magnitude and phase.

simulate(netlist) -> string

Auto-detects analysis type and runs it.

parse_nodes(netlist) -> string

Returns the equation map (available signals) without running a simulation.

Schematic rendering methods

kdl_to_svg(kdl) -> string

Parses a KDL circuit description and returns an SVG string.

kdl_to_spice(kdl) -> string

Generates a SPICE netlist from a KDL circuit description.

kdl_extract_params(kdl) -> string

Extracts editable parameters from a KDL circuit.

Complete example

import init, { SimulationEngine } from './pkg/spice_rs_wasm.js';

async function main() {
    await init();
    const engine = new SimulationEngine();

    const netlist = `
Voltage Divider
V1 vdd 0 DC 3.3
R1 vdd mid 10K
R2 mid 0 10K
.OP
.END
`;

    const result = JSON.parse(engine.dc_op(netlist));
    console.log("mid =", result.nodes.mid, "V");
}

main();

Error handling

All methods throw a JsError on failure.


sparse-rs API

sparse-rs is a pure Rust sparse matrix solver with two backends:

Both solve where A is a sparse square matrix.

Matrix construction

All backends use CscMatrix (compressed sparse column) as input:

use sparse_rs::CscMatrix;

let mat = CscMatrix::from_triplets(
    n,        // matrix dimension (n x n)
    &rows,    // row indices
    &cols,    // column indices
    &values,  // nonzero values
);

Duplicate entries at the same (row, col) are summed, matching the standard assembly convention for circuit matrices.

KLU backend

Three-phase workflow: symbolic analysis, numeric factorization, solve.

use sparse_rs::klu::{symbolic, numeric, solve};

// Phase 1: symbolic analysis (depends only on sparsity pattern)
let sym = symbolic(&mat);

// Phase 2: numeric factorization
let num = numeric(&mat, &sym).expect("factorization failed");

// Phase 3: solve Ax = b (solution overwrites b in-place)
let mut b = vec![1.0, 2.0, 3.0];
solve(&num, &sym, &mut b).expect("solve failed");

Symbolic analysis is expensive but only needs to run once for a given sparsity pattern. Numeric factorization and solve are fast and can be repeated when matrix values change but the pattern stays the same.

Markowitz backend

Two-phase workflow: combined ordering + factorization, then solve.

use sparse_rs::markowitz::{order_and_factor, solve};

let lu = order_and_factor(&mat).expect("factorization failed");

let mut b = vec![1.0, 2.0, 3.0];
solve(&lu, &mut b).expect("solve failed");

Choosing a backend

KLU Markowitz
Best for Large sparse systems (100+ nodes) Small to medium systems
Reordering AMD + BTF block decomposition Markowitz criterion
Refactorization Fast (reuse symbolic) Must re-order
Complex support Not yet Yes
Used by spice-rs (default solver) spice-rs (AC analysis complex solve)