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¶
Linear Devices¶
Nonlinear and Switching Devices¶
Time-Varying Sources¶
Control and Signal Blocks¶
HysteresisController
¶
HysteresisController(upper: float = 1.0, lower: float = -1.0, name: str = '')
Parser and Simulation Entry Points¶
Solver Configuration¶
LinearSolverKind
¶
Bases: Enum
PreconditionerKind
¶
Bases: Enum
Integration and Timestep¶
Integrator
¶
Bases: Enum
StepMode
¶
Bases: Enum
TimestepMethod
¶
Bases: Enum
DC and Convergence¶
DCStrategy
¶
Bases: Enum
Periodic and Harmonic Analysis¶
Thermal and Loss Modeling¶
ThermalCouplingPolicy
¶
Bases: Enum
Events and Backend Telemetry¶
SimulationEventType
¶
Bases: Enum
FallbackReasonCode
¶
Bases: Enum
Convergence Monitoring¶
Validation and Benchmarks¶
RLCAnalytical
¶
RLCAnalytical(R: float, L: float, C: float, V_source: float, V_initial: float, I_initial: float)
RLCDamping
¶
Bases: Enum
compare_waveforms
¶
compare_waveforms(name: str, simulated: List[tuple[float, float]], analytical: List[tuple[float, float]], threshold: float = 0.001) -> ValidationResult_v2
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
|
|
ParsedNetlist
|
|
ParsedNetlist
|
|
ParsedNetlist
|
|
ParsedNetlist
|
|
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]
get_pwm_duty
¶
get_pwm_duty(comp_id: str) -> float
Return current computed duty cycle [0, 1] for a PWM component.
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
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: |
required |
path
|
Any
|
Output file path; the extension drives the format unless
|
required |
format
|
str | None
|
One of |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
The resolved :class: |
Raises:
| Type | Description |
|---|---|
ImportError
|
If |
ValueError
|
If the format cannot be inferred and |
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 tonetlistsvgCLI with the bundled analog skin. SVG is native output; PNG is supported viarsvg-convertorcairosvg.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 |
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: |
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: |
required |
path
|
Any
|
Output file path; the extension drives the format unless
|
required |
format
|
str | None
|
One of |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
The resolved :class: |
Raises:
| Type | Description |
|---|---|
ImportError
|
If |
ValueError
|
If the format cannot be inferred and |
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 |
required |
svg_path
|
Any
|
Output SVG path (must end in |
required |
position_hints
|
dict[str, dict[str, Any]] | None
|
Reserved for future use; currently must be |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
The |
Path
|
class: |
Raises:
| Type | Description |
|---|---|
ImportError
|
If the netlistsvg CLI isn't available locally. |
RuntimeError
|
If the netlistsvg subprocess fails. |
NotImplementedError
|
If |
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 |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
SchematicLayout
|
class: |
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 |
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: |
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 |
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 |
kind |
str
|
Canonical kind string (e.g. |
x, |
y
|
Center of the component graphic in mm. |
rotation |
int
|
One of |
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 |
to |
WireEndpoint
|
Destination endpoint. |
path |
tuple[tuple[float, float], ...]
|
Polyline as a list of |
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 |
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. |
role_to_component |
dict[str, str]
|
Map from a template-defined role label
( |
anchor_nodes |
dict[str, int]
|
Map from a template-defined anchor-node label
( |