Skip to content

API Reference

This page is generated from the pulsim package surface (stubs + public exports).

Canonical usage

For new integrations, prefer YamlParser + SimulationOptions + Simulator.

Circuit Runtime

Circuit

Circuit()

VirtualComponent

VirtualComponent()

MixedDomainStepResult

MixedDomainStepResult()

VirtualChannelMetadata

VirtualChannelMetadata()

Linear Devices

Resistor

Resistor(resistance: float, name: str = '')

Capacitor

Capacitor(capacitance: float, initial_voltage: float = 0.0, name: str = '')

Inductor

Inductor(inductance: float, initial_current: float = 0.0, name: str = '')

VoltageSource

VoltageSource(voltage: float, name: str = '')

CurrentSource

CurrentSource(current: float, name: str = '')

Nonlinear and Switching Devices

IdealDiode

IdealDiode(name: str = '')

IdealSwitch

IdealSwitch(name: str = '')

MOSFETParams

MOSFETParams()

MOSFET

MOSFET(params: MOSFETParams, name: str = '')

IGBTParams

IGBTParams()

IGBT

IGBT(params: IGBTParams, name: str = '')

Time-Varying Sources

PWMParams

PWMParams()

PWMVoltageSource

PWMVoltageSource(params: PWMParams, name: str = '')

SineParams

SineParams()

SineVoltageSource

SineVoltageSource(params: SineParams, name: str = '')

RampParams

RampParams()

RampGenerator

RampGenerator(params: RampParams, name: str = '')

PulseParams

PulseParams()

PulseVoltageSource

PulseVoltageSource(params: PulseParams, name: str = '')

Control and Signal Blocks

PIController

PIController(kp: float = 1.0, ki: float = 0.0, name: str = '')

PIDController

PIDController(kp: float = 1.0, ki: float = 0.0, kd: float = 0.0, name: str = '')

Comparator

Comparator(threshold: float = 0.0, name: str = '')

SampleHold

SampleHold(name: str = '')

RateLimiter

RateLimiter(max_rate: float = 1.0, name: str = '')

MovingAverageFilter

MovingAverageFilter(window_size: int = 10, name: str = '')

HysteresisController

HysteresisController(upper: float = 1.0, lower: float = -1.0, name: str = '')

LookupTable1D

LookupTable1D(x: List[float], y: List[float], name: str = '')

Parser and Simulation Entry Points

YamlParserOptions

YamlParserOptions()

YamlParser

YamlParser(options: YamlParserOptions = ...)

Simulator

Simulator(circuit: Circuit, options: SimulationOptions = ...)

SimulationOptions

SimulationOptions()

SimulationResult

SimulationResult()

Solver Configuration

Tolerances

Tolerances()

NewtonOptions

NewtonOptions()

NewtonResult

NewtonResult()

LinearSolverKind

Bases: Enum

PreconditionerKind

Bases: Enum

IterativeSolverConfig

IterativeSolverConfig()

LinearSolverStackConfig

LinearSolverStackConfig()

LinearSolverConfig

LinearSolverConfig()

LinearSolverTelemetry

LinearSolverTelemetry()

Integration and Timestep

Integrator

Bases: Enum

StepMode

Bases: Enum

TimestepMethod

Bases: Enum

TimestepConfig

TimestepConfig()

AdvancedTimestepConfig

AdvancedTimestepConfig()

RichardsonLTEConfig

RichardsonLTEConfig()

BDFOrderConfig

BDFOrderConfig()

StiffnessConfig

StiffnessConfig()

DC and Convergence

DCStrategy

Bases: Enum

GminConfig

GminConfig()

SourceSteppingConfig

SourceSteppingConfig()

PseudoTransientConfig

PseudoTransientConfig()

InitializationConfig

InitializationConfig()

DCConvergenceConfig

DCConvergenceConfig()

DCAnalysisResult

DCAnalysisResult()

Periodic and Harmonic Analysis

PeriodicSteadyStateOptions

PeriodicSteadyStateOptions()

PeriodicSteadyStateResult

PeriodicSteadyStateResult()

HarmonicBalanceOptions

HarmonicBalanceOptions()

HarmonicBalanceResult

HarmonicBalanceResult()

Thermal and Loss Modeling

ThermalCouplingPolicy

Bases: Enum

ThermalCouplingOptions

ThermalCouplingOptions()

ThermalDeviceConfig

ThermalDeviceConfig()

DeviceThermalTelemetry

DeviceThermalTelemetry()

ThermalSummary

ThermalSummary()

SwitchingEnergy

SwitchingEnergy()

LossBreakdown

LossBreakdown()

LossAccumulator

LossAccumulator()

EfficiencyCalculator

EfficiencyCalculator()

LossResult

LossResult()

SystemLossSummary

SystemLossSummary()

FosterStage

FosterStage()

FosterNetwork

FosterNetwork()

CauerStage

CauerStage()

CauerNetwork

CauerNetwork()

ThermalSimulator

ThermalSimulator()

ThermalLimitMonitor

ThermalLimitMonitor()

ThermalResult

ThermalResult()

Events and Backend Telemetry

SimulationEventType

Bases: Enum

SimulationEvent

SimulationEvent()

FallbackReasonCode

Bases: Enum

FallbackPolicyOptions

FallbackPolicyOptions()

FallbackTraceEntry

FallbackTraceEntry()

BackendTelemetry

BackendTelemetry()

Convergence Monitoring

IterationRecord

IterationRecord()

ConvergenceHistory

ConvergenceHistory()

VariableConvergence

VariableConvergence()

PerVariableConvergence

PerVariableConvergence()

Validation and Benchmarks

RCAnalytical

RCAnalytical(R: float, C: float, V_initial: float, V_final: float)

RLAnalytical

RLAnalytical(R: float, L: float, V_source: float, I_initial: float)

RLCAnalytical

RLCAnalytical(R: float, L: float, C: float, V_source: float, V_initial: float, I_initial: float)

RLCDamping

Bases: Enum

ValidationResult

ValidationResult()

compare_waveforms

compare_waveforms(name: str, simulated: List[tuple[float, float]], analytical: List[tuple[float, float]], threshold: float = 0.001) -> ValidationResult_v2

export_validation_csv

export_validation_csv(results: List[ValidationResult_v2]) -> str

export_validation_json

export_validation_json(results: List[ValidationResult_v2]) -> str

BenchmarkTiming

BenchmarkTiming()

BenchmarkResult

BenchmarkResult()

export_benchmark_csv

export_benchmark_csv(results: List[BenchmarkResult]) -> str

export_benchmark_json

export_benchmark_json(results: List[BenchmarkResult]) -> str

Pure-Python Utilities

ParsedNetlist dataclass

ParsedNetlist(circuit: Circuit, title: str = '', warnings: List[NetlistWarning] = list(), models: Dict[str, Any] = dict(), node_map: Dict[str, int] = dict())

Result of parsing a SPICE netlist.

NetlistParseError

NetlistParseError(message: str, line_number: Optional[int] = None, line_content: Optional[str] = None)

Bases: Exception

Error during netlist parsing with line context.

NetlistWarning dataclass

NetlistWarning(line_number: int, line_content: str, message: str)

Warning from netlist parsing.

parse_netlist

parse_netlist(netlist: str, *, strict: bool = False, default_mosfet_params: Optional[MOSFETParams] = None, default_igbt_params: Optional[IGBTParams] = None) -> Circuit

Parse a SPICE-like netlist string and return a Pulsim Circuit.

Parameters:

Name Type Description Default
netlist str

SPICE netlist string

required
strict bool

If True, raise error on unknown directives; if False, warn and skip

False
default_mosfet_params Optional[MOSFETParams]

Default MOSFET parameters when model not specified

None
default_igbt_params Optional[IGBTParams]

Default IGBT parameters when model not specified

None

Returns:

Type Description
Circuit

Configured Circuit object ready for simulation

Raises:

Type Description
NetlistParseError

On syntax errors or invalid device specifications

Example

netlist = ''' ... * RC Circuit ... V1 in 0 5 ... R1 in out 1k ... C1 out 0 1u IC=0 ... .end ... ''' ckt = parse_netlist(netlist) print(ckt.num_devices()) 3

parse_netlist_verbose

parse_netlist_verbose(netlist: str, *, strict: bool = False, default_mosfet_params: Optional[MOSFETParams] = None, default_igbt_params: Optional[IGBTParams] = None) -> ParsedNetlist

Parse netlist and return detailed result with warnings.

Parameters:

Name Type Description Default
netlist str

SPICE netlist string

required
strict bool

If True, raise error on unknown directives

False
default_mosfet_params Optional[MOSFETParams]

Default MOSFET parameters

None
default_igbt_params Optional[IGBTParams]

Default IGBT parameters

None

Returns:

Type Description
ParsedNetlist

ParsedNetlist object containing:

ParsedNetlist
  • circuit: The built Circuit object
ParsedNetlist
  • title: Circuit title (first comment line)
ParsedNetlist
  • warnings: List of NetlistWarning objects
ParsedNetlist
  • models: Dict of parsed .model definitions
ParsedNetlist
  • node_map: Dict mapping node names to indices
Example

result = parse_netlist_verbose(netlist) print(f"Title: {result.title}") for w in result.warnings: ... print(f"Warning: {w}")

parse_value

parse_value(value_str: str, line_number: Optional[int] = None) -> float

Parse a value string with optional engineering suffix.

Supports
  • Plain numbers: '100', '1.5', '-3.14'
  • Scientific notation: '1e-6', '1.5E3'
  • Engineering suffixes: '10k', '100u', '1.5meg', '4.7n'

Parameters:

Name Type Description Default
value_str str

Value string to parse

required
line_number Optional[int]

Line number for error reporting

None

Returns:

Type Description
float

Parsed float value

Raises:

Type Description
NetlistParseError

If value cannot be parsed

Examples:

>>> parse_value('100')
100.0
>>> parse_value('10k')
10000.0
>>> parse_value('1.5meg')
1500000.0
>>> parse_value('100u')
0.0001
>>> parse_value('4.7n')
4.7e-09

SignalEvaluator

SignalEvaluator(circuit_data: dict)

Evaluates a signal-flow DAG from a circuit description dict each step.

The evaluator is deliberately independent of any GUI framework. It operates on plain Python dicts (the circuit_data format) and uses the native C++ control objects from pulsim._pulsim when available, falling back to pure-Python equivalents otherwise.

Parameters

circuit_data : dict Circuit description with keys "components", "wires", "node_map", and "node_aliases". The format is identical to the dict produced by the GUI's SimulationService.convert_gui_circuit(), but it can also be constructed programmatically (no GUI needed).

Examples

See module docstring for a complete usage example.

build

build() -> None

Parse the circuit dict, build the signal DAG, and initialise state.

Must be called once before :meth:step. Call again to rebuild after the circuit description changes.

Raises

AlgebraicLoopError When a directed cycle exists among the signal-domain blocks.

has_signal_blocks

has_signal_blocks() -> bool

Return True if there are any evaluable signal blocks.

pwm_components

pwm_components() -> dict[str, str]

Return {comp_id: backend_name} for PWM generators with DUTY_IN connected.

update_probes

update_probes(probe_values: dict[str, float]) -> None

Inject probe measurements into the evaluator state.

Call this after each electrical simulation step with the latest measured values so that feedback blocks (VOLTAGE_PROBE, CURRENT_PROBE) reflect the true circuit state.

Parameters

probe_values : dict[str, float] {component_id: measured_value} mapping. Unrecognised IDs are silently ignored.

step

step(t: float) -> dict[str, float]

Evaluate all signal blocks in topological order at time t.

Parameters

t : float Current simulation time in seconds.

Returns

dict[str, float] {comp_id: output_value} for every signal block. PWM duty values are clamped to [0, 1].

get_pwm_duty

get_pwm_duty(comp_id: str) -> float

Return current computed duty cycle [0, 1] for a PWM component.

reset

reset() -> None

Reset all stateful controller objects (integrators, PI state, etc.).

AlgebraicLoopError

AlgebraicLoopError(cycle_ids: list[str])

Bases: RuntimeError

Raised when a cycle is detected in the signal-flow graph.

Attributes

cycle_ids : list[str] Component names (or IDs) that form the cycle.

Performance Utilities and Enums

SIMDLevel

Bases: Enum

DeviceType

Bases: Enum

DeviceHint

Bases: Enum

SolverStatus

Bases: Enum

detect_simd_level

detect_simd_level() -> SIMDLevel

simd_vector_width

simd_vector_width() -> int

backend_capabilities

backend_capabilities() -> Dict[str, bool]

solver_status_to_string

solver_status_to_string(status: SolverStatus) -> str

Schematic Rendering

See the Schematic Rendering user guide for the workflow and backends.

render

Schematic rendering with pluggable backends.

Default backend is netlistsvg (Phase 4F) — production schematic renderer built on ELK + a purpose-tuned analog SVG skin. Produces textbook-quality output (proper resistor / capacitor / inductor / diode / voltage-source / ground symbols + orthogonal Manhattan wires) for any circuit topology netlistsvg knows about. Switching devices that aren't in the analog skin (MOSFET/IGBT/vcswitch) currently render as labeled generic boxes; a follow-up change (add-pulsim-analog-skin) extends the SVG skin with proper symbols for those.

Other backends available via PULSIM_SCHEMATIC_BACKEND env var:

netlistsvg  (default)  — netlistsvg CLI + analog skin
elk                    — ELK layered + schemdraw symbols (in-tree)
spring                 — legacy force-directed + templates + schemdraw

The ELK and spring backends produce a :class:SchematicLayout which is still useful when a GUI wants component coordinates. netlistsvg owns the layout internally; if a layout object is needed under netlistsvg, fall back to ELK by setting the env var.

render_layout

render_layout(layout: SchematicLayout, path: Any, format: str | None = None) -> Path

Render a pre-computed layout to a file.

Parameters:

Name Type Description Default
layout SchematicLayout

A :class:SchematicLayout (typically from :func:compute_layout).

required
path Any

Output file path; the extension drives the format unless format= is passed.

required
format str | None

One of "svg", "png", "pdf", "jpg".

None

Returns:

Type Description
Path

The resolved :class:pathlib.Path of the written file.

Raises:

Type Description
ImportError

If schemdraw is not installed.

ValueError

If the format cannot be inferred and format= is not passed.

render

render(circuit: Any, path: Any, format: str | None = None, position_hints: dict[str, dict[str, Any]] | None = None) -> Path

Render a Pulsim Circuit to a schematic file.

The default backend is netlistsvg (Phase 4F) — production-grade output with proper analog symbols. Override via the PULSIM_SCHEMATIC_BACKEND environment variable:

  • netlistsvg (default): subprocess to netlistsvg CLI with the bundled analog skin. SVG is native output; PNG is supported via rsvg-convert or cairosvg.
  • elk: in-tree ELK layered layout + schemdraw render.
  • spring: legacy force-directed + templates + schemdraw.

The output format is inferred from the path extension (.svg, .png, .pdf, .jpg) unless format= is passed.

Position hints (netlistsvg backend only): position_hints is an optional dict mapping component names to either {"layer": int, "slot": int} (semantic grid placement) or {"x": float, "y": float} (absolute layout units). Hinted cells land at the user-specified coordinates; un-hinted cells use the default auto-layout. Useful when the auto-layout produces an unconventional arrangement and you want a textbook layout.

Parameters:

Name Type Description Default
circuit Any

A Pulsim Circuit (or anything matching the components() / ground() / node_position_hint() contract).

required
path Any

Output file path.

required
format str | None

Optional explicit format override.

None
position_hints dict[str, dict[str, Any]] | None

Optional placement hints (netlistsvg backend).

None

Returns:

Name Type Description
The Path

class:pathlib.Path of the written file.

render_layout

render_layout(layout: SchematicLayout, path: Any, format: str | None = None) -> Path

Render a pre-computed layout to a file.

Parameters:

Name Type Description Default
layout SchematicLayout

A :class:SchematicLayout (typically from :func:compute_layout).

required
path Any

Output file path; the extension drives the format unless format= is passed.

required
format str | None

One of "svg", "png", "pdf", "jpg".

None

Returns:

Type Description
Path

The resolved :class:pathlib.Path of the written file.

Raises:

Type Description
ImportError

If schemdraw is not installed.

ValueError

If the format cannot be inferred and format= is not passed.

render_netlistsvg

render_netlistsvg(circuit: Any, svg_path: Any, position_hints: dict[str, dict[str, Any]] | None = None) -> Path

Render a Pulsim Circuit to SVG via netlistsvg + analog skin.

position_hints is reserved but not yet implemented — see openspec/changes/add-schematic-position-hints for the tracking proposal. The empirical finding: netlistsvg 1.0.2's --layout flag has two real upstream bugs (a) Promise-path renders the SVG into undefined when elkData is supplied, (b) overriding (x, y) on cells without recomputing the cached edge sections produces tangled wires through empty space. Both require either a fork of netlistsvg or replicating its render layer in Python — neither feasible as an MVP. Until a path is implemented, passing position_hints raises :class:NotImplementedError.

Parameters:

Name Type Description Default
circuit Any

Pulsim Circuit (uses components() and ground()).

required
svg_path Any

Output SVG path (must end in .svg).

required
position_hints dict[str, dict[str, Any]] | None

Reserved for future use; currently must be None or empty.

None

Returns:

Name Type Description
The Path

class:pathlib.Path of the written SVG.

Raises:

Type Description
ImportError

If the netlistsvg CLI isn't available locally.

RuntimeError

If the netlistsvg subprocess fails.

NotImplementedError

If position_hints is non-empty (see above).

compute_layout

compute_layout(circuit: Any) -> SchematicLayout

Build a deterministic :class:SchematicLayout for a Circuit.

Default backend is ELK (Eclipse Layout Kernel via elkjs running on Node.js) — a Sugiyama layered algorithm with orthogonal edge routing that produces textbook-style schematics with left-to-right power flow and a clear ground rail at the bottom. The legacy in-tree spring-layout + topology-templates + parallel-pair + ground-rail pipeline is still callable as a fallback by setting the environment variable PULSIM_SCHEMATIC_BACKEND=spring (used for environments without Node.js installed, or for backwards-compat regression).

Parameters:

Name Type Description Default
circuit Any

Any object exposing components(), ground(), and node_position_hint(node_id) matching the Pulsim Circuit contract.

required

Returns:

Name Type Description
A SchematicLayout

class:SchematicLayout with every component placed, wires

SchematicLayout

connecting shared-node terminals, junctions where 3+ terminals

SchematicLayout

meet, and a canvas bounding box.

Raises:

Type Description
ImportError

On the ELK path, if Node.js isn't on PATH (the user- facing message names the install hint). On the spring fallback path, if networkx isn't installed.

SchematicLayout dataclass

SchematicLayout(components: dict[str, ComponentPlacement], wires: tuple[Wire, ...], junctions: tuple[tuple[float, float], ...], canvas: BoundingBox, schema_version: str = SCHEMATIC_SCHEMA_VERSION)

Top-level schematic layout payload.

Carries every placed component, the wires connecting them, junction dots, and the canvas bounding box. Serializes to a single JSON document via :meth:to_json; round-trips via :meth:from_json.

Attributes:

Name Type Description
components dict[str, ComponentPlacement]

Component name → :class:ComponentPlacement.

wires tuple[Wire, ...]

Tuple of wires drawn on the canvas.

junctions tuple[tuple[float, float], ...]

Coordinates where 3+ wire endpoints meet (mm).

canvas BoundingBox

Bounding box covering all placements with margin.

schema_version str

Stable string "schematic-v1"; bumped on breaking schema changes.

ComponentPlacement dataclass

ComponentPlacement(name: str, kind: str, x: float, y: float, rotation: int, terminal_anchors: tuple[TerminalAnchor, ...] = tuple())

Placement of one component on the canvas.

Attributes:

Name Type Description
name str

User-facing component name (matches Circuit.components()).

kind str

Canonical kind string (e.g. "resistor", "mosfet").

x, y

Center of the component graphic in mm.

rotation int

One of {0, 90, 180, 270} (degrees, CW from +x).

terminal_anchors tuple[TerminalAnchor, ...]

Per-terminal anchor coordinates (pin order).

Wire dataclass

Wire(from_: WireEndpoint, to: WireEndpoint, path: tuple[tuple[float, float], ...] = tuple())

A wire connecting two component terminals along an explicit path.

Phase 2 emits straight-line wires: path contains the two endpoint coordinates only. Manhattan routing is a follow-up change.

Attributes:

Name Type Description
from_ WireEndpoint

Source endpoint. JSON key is "from" (Python's reserved from keyword prevents using it as a field name directly).

to WireEndpoint

Destination endpoint.

path tuple[tuple[float, float], ...]

Polyline as a list of [x, y] pairs in mm.

WireEndpoint dataclass

WireEndpoint(component: str, terminal: int)

One endpoint of a wire, identified by (component_name, terminal_index).

TerminalAnchor dataclass

TerminalAnchor(index: int, x: float, y: float, node: int)

Where one terminal of a component connects to the canvas.

Attributes:

Name Type Description
index int

Terminal position in the component's pin order (0-based).

x, y

Anchor coordinate in mm.

node int

Electrical node index this terminal belongs to.

BoundingBox dataclass

BoundingBox(x: float, y: float, width: float, height: float, unit: str = 'mm')

Canvas bounding box in millimeters.

Attributes:

Name Type Description
x, y

Origin of the bounding box (top-left corner).

width, height

Extent along +x and +y axes.

unit str

Always "mm" for schematic-v1.

recognize_all

recognize_all(components: list) -> list[RecognizedTemplate]

Run every recognizer in priority order, dropping overlapping matches.

A match is dropped when any of its components has already been claimed by a higher-priority match. Determinism: same input order → same output.

RecognizedTemplate dataclass

RecognizedTemplate(template_id: str, role_to_component: dict[str, str], anchor_nodes: dict[str, int])

One matched sub-topology.

Attributes:

Name Type Description
template_id str

Canonical template name, e.g. "bridge_rectifier".

role_to_component dict[str, str]

Map from a template-defined role label ("D1", "L", "Q_hi" …) to the user-visible component name in the circuit.

anchor_nodes dict[str, int]

Map from a template-defined anchor-node label ("ac_a", "dc_pos" …) to the integer electrical-node index that plays that role.