Skip to content

Migration Guide: Python-Only v1 Runtime

This guide documents the migration to the unified v1 kernel with a Python-only user-facing runtime.

1. What Changed

Removed / Unsupported User Surfaces

  • Legacy CLI execution flow
  • Legacy gRPC server/client workflow
  • JSON netlist loading path

Supported User Surface

  • Python package pulsim
  • YAML netlists (schema: pulsim-v1)
  • Python benchmark/parity/stress tooling in benchmarks/

2. Netlist Migration (JSON -> YAML)

JSON loaders are no longer part of the supported runtime path.

Use versioned YAML:

schema: pulsim-v1
version: 1
components:
  - type: resistor
    name: R1
    nodes: [in, out]
    value: 1k

3. Runtime Migration

Before (removed)

  • pulsim CLI command flows
  • Remote gRPC client/server product workflow

After (supported)

import pulsim as ps

parser = ps.YamlParser(ps.YamlParserOptions())
circuit, options = parser.load("circuit.yaml")

options.newton_options.num_nodes = int(circuit.num_nodes())
options.newton_options.num_branches = int(circuit.num_branches())

sim = ps.Simulator(circuit, options)
result = sim.run_transient(circuit.initial_state())

Canonical transient mode keys

No runtime suportado, a escolha de caminho transiente é canônica por modo:

  • simulation.step_mode: fixed
  • simulation.step_mode: variable

As chaves legadas simulation.backend, simulation.sundials e os campos antigos de simulation.fallback não fazem mais parte do schema ativo.

Before/After: legacy backend -> canonical mode

Before (legacy, removed in strict migration path):

simulation:
  backend: auto
  sundials:
    enabled: true
    family: ida
  adaptive_timestep: true
  dt: 1e-7

After (canonical fixed-step native core):

simulation:
  step_mode: fixed
  dt: 1e-7
  dt_min: 1e-9
  dt_max: 1e-7

After (canonical variable-step native core):

simulation:
  step_mode: variable
  dt: 1e-7
  dt_min: 1e-9
  dt_max: 2e-6
  timestep:
    preset: power_electronics

Com strict = True, esses campos geram erro de campo desconhecido (PULSIM_YAML_E_UNKNOWN_FIELD). Em strict = False, geram warning com o mesmo código.

Schema Evolution Policy (v1)

  • Deprecated (migration window): simulation.adaptive_timestep
  • Accepted in schema pulsim-v1, but emits warning PULSIM_YAML_W_DEPRECATED_FIELD with replacement guidance to simulation.step_mode: fixed|variable.
  • Removed: simulation.backend, simulation.sundials, simulation.fallback.enable_backend_escalation, simulation.fallback.backend_escalation_threshold, simulation.fallback.enable_native_reentry, simulation.fallback.sundials_recovery_window, and simulation.advanced block.
  • Parser emits deterministic unknown-field diagnostics (PULSIM_YAML_E_UNKNOWN_FIELD) for these keys.

Before/After: procedural compatibility and canonical runtime

Before (procedural path, still supported in migration window):

import pulsim as ps

times, states, ok, msg = ps.run_transient(
    circuit, 0.0, 1e-3, 1e-6, circuit.initial_state()
)

After (canonical class/runtime surface):

import pulsim as ps

opts = ps.SimulationOptions()
opts.tstart = 0.0
opts.tstop = 1e-3
opts.dt = 1e-6

sim = ps.Simulator(circuit, opts)
result = sim.run_transient(circuit.initial_state())

Both paths share the same v1 kernel semantics; prefer Simulator for new code.

Canonical expert knobs

Use the top-level simulation fields for expert tuning:

simulation:
  step_mode: variable
  integrator: trbdf2
  solver:
    order: [gmres]
    iterative:
      preconditioner: ilut
      max_iterations: 300
      tolerance: 1e-8

4. Removed API/Workflow Mapping

Removed workflow Replacement
CLI run/validate/info/sweep Python runtime + benchmarks/*.py runners
gRPC remote simulation docs Local Python runtime usage
JSON netlist loader docs/tests YAML parser (YamlParser)
Planned placeholder high-level suites Active runtime/benchmark/validation suites

5. Versioned Deprecation Timeline

Version Status Notes
v0.2.0 Deprecation window Python-only surface declared; legacy docs marked stale
v0.3.0 Removal Legacy CLI/gRPC/JSON user-facing guidance removed from primary docs
v0.4.0 Enforcement Supported workflows restricted to Python + YAML + benchmark/parity/stress toolchain

6. Migration Notes: PulsimGui Converter Integration

Canonicalização de tipos

O conversor do PulsimGui deve emitir tipos que o parser normaliza para IDs canônicos (ex.: OP_AMP -> op_amp, PI_CONTROLLER -> pi_controller, CIRCUIT_BREAKER -> circuit_breaker).

Recomendação: sempre serializar o tipo canônico em minúsculo para reduzir ambiguidade no pipeline GUI -> YAML -> backend.

Regras de modelagem no backend

  • bjt_npn e bjt_pnp: surrogate interno baseado em mosfet.
  • thyristor, triac, fuse, circuit_breaker: composição com switch e controlador virtual/event-driven.
  • relay: composição com dois switch (NO/NC) + controlador virtual da bobina.
  • saturable_inductor: inductor elétrico + controlador virtual de indutância efetiva.
  • coupled_inductor: dois ramos inductor + controlador virtual de acoplamento.
  • transformer com magnetic_core: mantém ramo elétrico ideal + telemetria canônica de perdas magnéticas (<name>.core_loss).
  • voltage_probe/current_probe/power_probe/scope/mux/demux: componentes virtuais (não estampam MNA).

Migração para component.magnetic_core canônico

Para novos modelos magnéticos, prefira o bloco canônico:

magnetic_core:
  enabled: true
  model: saturation
  core_loss_k: 0.1
  core_loss_alpha: 2.0
  core_loss_freq_coeff: 1e-4

Regras práticas de migração:

  • Evite parâmetros soltos fora de magnetic_core para perdas magnéticas.
  • Use model: saturation para curva de saturação simples, ou model: hysteresis quando precisar memória de ciclo (<component>.h_state).
  • Para saturable_inductor, mantenha também os parâmetros elétricos (inductance, saturation_current, saturation_inductance) no componente.
  • No frontend, não reconstrua curvas térmicas/magnéticas; use os canais exportados pelo backend (<component>.core_loss, <component>.h_state, T(<component>.core) quando perdas+térmico estiverem ativos).

Pinagem e validação

Ative strict mode no parser durante integração:

opts = ps.YamlParserOptions()
opts.strict = True
parser = ps.YamlParser(opts)

Isso garante diagnóstico estável para:

  • pinagem inválida (ex.: relay sem COM/NO/NC);
  • parâmetros fora de faixa (ex.: duty_min > duty_max);
  • blocos de controle com configuração inconsistente.

Gate mínimo para CI do conversor

PYTHONPATH=build/python pytest -q python/tests/test_gui_component_parity.py
PYTHONPATH=build/python pytest -q python/tests/test_runtime_bindings.py
./build-test/core/pulsim_simulation_tests "[v1][yaml][gui-parity]"

7. Upgrade Checklist

  1. Replace any JSON netlist assets with YAML pulsim-v1 netlists.
  2. Remove CLI automation and migrate to Python runners.
  3. Remove gRPC-dependent user scripts from active workflows.
  4. Update CI jobs to run Python benchmark/parity/stress scripts.
  5. Add GUI parity regression gate (test_gui_component_parity.py) in CI.
  6. Validate with openspec validate refactor-python-only-v1-hardening --strict.