Python API Reference¶
A superfície suportada para usuários é a API Python do módulo pulsim.
Fluxo principal de uso¶
YamlParsercarrega netlist e opções.- Ajuste fino de
SimulationOptionsem runtime. Simulatorexecuta DC/transiente/periódico.SimulationResultentrega sinais e telemetria.
Tipos principais¶
| Tipo | Papel |
|---|---|
YamlParserOptions, YamlParser |
Parse/validação de YAML pulsim-v1. |
Circuit |
Grafo/circuito pronto para simulação. |
SimulationOptions |
Configuração completa da simulação. |
Simulator |
Execução de dc_operating_point, run_transient, run_periodic_shooting, run_harmonic_balance. |
SimulationResult |
Sinais (time, states), eventos, telemetria e resumos de perdas/térmico. |
As APIs de transiente em Python (Simulator.run_transient, run_transient_streaming, run_transient_shared e ps.run_transient) aplicam perfil robusto por padrão para reduzir falhas de convergência.
Compatibilidade de migração¶
ps.run_transient(...)permanece disponível para compatibilidade procedural.- A superfície canônica para novas integrações é
YamlParser+SimulationOptions+Simulator. - Em casos de migração YAML, prefira
simulation.step_modeem vez desimulation.adaptive_timestep(legado) e evite campos removidos comosimulation.backend/simulation.sundials/simulation.advanced.
Configuração tipada de núcleo magnético¶
Para fluxos Python-first com componentes virtuais, a API expõe:
MagneticCoreConfigMagneticCoreConfigErrorapply_magnetic_core_config(...)
Exemplo (merge determinístico em numeric_params + metadata):
import pulsim as ps
cfg = ps.MagneticCoreConfig(
model="hysteresis",
loss_policy="loss_summary",
core_loss_k=0.2,
core_loss_alpha=2.0,
core_loss_freq_coeff=1e-4,
hysteresis_strength=0.25,
)
numeric_params, metadata = ps.apply_magnetic_core_config({}, {}, cfg)
print(numeric_params["core_loss_k"])
print(metadata["magnetic_core_model"])
Quando inválido, cfg.validate() (ou o merge) lança MagneticCoreConfigError
com code e field estáveis para automação.
Exemplo completo¶
import pulsim as ps
parser = ps.YamlParser(ps.YamlParserOptions())
circuit, options = parser.load("benchmarks/circuits/buck_converter.yaml")
options.newton_options.num_nodes = int(circuit.num_nodes())
options.newton_options.num_branches = int(circuit.num_branches())
options.linear_solver = ps.LinearSolverStackConfig.defaults()
options.integrator = ps.Integrator.TRBDF2
options.step_mode = ps.StepMode.Variable
sim = ps.Simulator(circuit, options)
result = sim.run_transient(circuit.initial_state())
print("success:", result.success)
print("steps:", result.total_steps)
print("newton_total:", result.newton_iterations_total)
print("linear_fallbacks:", result.linear_solver_telemetry.total_fallbacks)
print("backend_caps:", ps.backend_capabilities())
Atalho recomendado para transiente¶
Para uso direto em notebook, ps.run_transient(...) agora aplica fallback automático
de robustez por padrão:
- retry com
dtmenor e mais iterações de Newton; - regularização automática (bleeders + clamp de não linearidades) em caso de falha persistente.
Você pode desativar:
times, states, ok, msg = ps.run_transient(
ckt, t0, t1, dt, x0,
robust=False,
auto_regularize=False,
)
Enums importantes¶
Integrator:Trapezoidal,BDF1..BDF5,TRBDF2,RosenbrockW,SDIRK2ControlUpdateMode:Auto,Continuous,DiscreteLinearSolverKind:SparseLU,EnhancedSparseLU,KLU,GMRES,BiCGSTAB,CGPreconditionerKind:None_,Jacobi,ILU0,ILUT,AMG(quando disponível)SolverStatus,DCStrategy,SimulationEventType,FallbackReasonCode
Configurações que mais importam¶
Solver linear¶
LinearSolverStackConfig.orderLinearSolverStackConfig.fallback_orderLinearSolverStackConfig.auto_selectIterativeSolverConfig.preconditioner,max_iterations,tolerance
Newton e convergência¶
NewtonOptions.max_iterationsNewtonOptions.enable_limitingNewtonOptions.max_voltage_step/max_current_step
Timestep e integrador¶
SimulationOptions.step_mode(StepMode.FixedouStepMode.Variable)SimulationOptions.control_modeSimulationOptions.control_sample_timeSimulationOptions.formulation_mode(FormulationMode.ProjectedWrapperouFormulationMode.Direct)SimulationOptions.direct_formulation_fallbackSimulationOptions.integratorSimulationOptions.adaptive_timestepSimulationOptions.timestep_configSimulationOptions.lte_config
O caminho suportado usa o core nativo com step_mode + formulation_mode.
Controle em malha fechada¶
import pulsim as ps
options.control_mode = ps.ControlUpdateMode.Auto
options.control_sample_time = 0.0 # 0 => auto/continuous path
Semântica:
Auto: usacontrol_sample_timese> 0; caso contrário tenta inferir por frequência PWM.Continuous: força atualização contínua de controle.Discrete: aplica amostragem global para blocos PI/PID.
Térmico e perdas¶
SimulationOptions.enable_lossesSimulationOptions.switching_energySimulationOptions.thermalSimulationOptions.thermal_devices
Resultados para análise¶
Campos úteis de SimulationResult:
time,stateseventssuccess,final_status,messagenewton_iterations_total,timestep_rejectionslinear_solver_telemetry,fallback_traceloss_summary,thermal_summarycomponent_electrothermal(deterministic per-component loss + temperature telemetry)virtual_channels,virtual_channel_metadata
Traços térmicos canônicos no transiente¶
Quando as três condições abaixo são verdadeiras:
options.enable_losses == Trueoptions.thermal.enable == True- componente com thermal habilitado (
options.thermal_devices[name].enabled == True)
o backend exporta em result.virtual_channels um canal térmico por componente no formato:
T(<component_name>)(ex.:T(M1),T(Rload))
Contrato:
len(result.virtual_channels["T(M1)"]) == len(result.time)component_electrothermal["M1"].final_temperature == last(T(M1))component_electrothermal["M1"].peak_temperature == max(T(M1))component_electrothermal["M1"].average_temperature == mean(T(M1))
Metadata recomendada para front-end (preenchida no backend):
result.virtual_channel_metadata["T(M1)"].domain == "thermal"component_type == "thermal_trace"source_component == "M1"unit == "degC"
Electrothermal Result Example¶
result = sim.run_transient(circuit.initial_state())
for item in result.component_electrothermal:
print(item.component_name, item.total_loss, item.peak_temperature)
trace_m1 = result.virtual_channels["T(M1)"]
meta_m1 = result.virtual_channel_metadata["T(M1)"]
print("trace samples:", len(trace_m1), "time samples:", len(result.time))
print("meta:", meta_m1.domain, meta_m1.source_component, meta_m1.unit)
component_electrothermal inclui todos os componentes elétricos não virtuais, com
campos térmicos determinísticos mesmo quando a porta térmica não está habilitada.
For full YAML + Python electrothermal setup (global thermal block, component thermal ports, strict/non-strict parser behavior), see Electrothermal Workflow.