Averaged Converter Modeling¶
This guide defines the backend contract for averaged-converter transient mode.
Scope and MVP Limits¶
Current backend support:
- topologies:
buck,boost,buck_boost - operating modes:
ccm,dcm,auto - execution mode: transient (
Simulator.run_transient(...)) - duty command: constant scalar (
simulation.averaged_converter.duty) - envelope policy:
strictorwarn(CCM-only check)
Current explicit non-goals:
- no automatic averaged-model synthesis for arbitrary topologies
- no implicit fallback to switched transient on averaged failures
- no backend consumption of controller/PWM duty channels in averaged mode yet
YAML Contract¶
Configure averaged mode in simulation.averaged_converter:
simulation:
tstart: 0.0
tstop: 350e-6
dt: 0.2e-6
averaged_converter:
enabled: true
topology: boost # buck | boost | buck_boost
operating_mode: auto # ccm | dcm | auto
envelope_policy: warn # strict | warn
vin_source: Vin # voltage_source component name
inductor: L1 # inductor component name
capacitor: C1 # capacitor component name
load_resistor: Rload # resistor component name
output_node: out # output node name
duty: 0.4
duty_min: 0.0
duty_max: 0.95
switching_frequency_hz: 100000.0
initial_inductor_current: 0.0
initial_output_voltage: 0.0
ccm_current_threshold: 0.0
Strict parser/runtime checks include:
- missing mapped fields when
enabled=true - invalid
topology,operating_mode, orenvelope_policy - invalid duty bounds (
0 <= duty_min <= duty <= duty_max <= 1) - invalid
ccm_current_threshold - invalid
switching_frequency_hz(> 0) - invalid mapped component types (for example mapping
inductorto a resistor)
Python API Surface¶
import pulsim as ps
parser = ps.YamlParser(ps.YamlParserOptions())
circuit, options = parser.load("examples/10_buck_averaged_mvp_backend.yaml")
options.newton_options.num_nodes = int(circuit.num_nodes())
options.newton_options.num_branches = int(circuit.num_branches())
result = ps.Simulator(circuit, options).run_transient(circuit.initial_state())
print(result.success, result.diagnostic.name, result.message)
Related typed enums/options:
AveragedConverterOptionsAveragedConverterTopologyAveragedOperatingModeAveragedEnvelopePolicy
Diagnostics¶
Canonical averaged runtime diagnostics:
AveragedInvalidConfigurationAveragedUnsupportedConfigurationAveragedOutOfEnvelopeAveragedSolverFailure
Behavior is deterministic:
operating_mode=ccm+strict: fails withAveragedOutOfEnvelopeoperating_mode=ccm+warn: run succeeds with out-of-envelope warning in messageoperating_mode=dcm|auto: uses DCM-capable equations and does not raise CCM-envelope failure
Result Channels and Metadata¶
Successful averaged runs publish canonical virtual channels:
Iavg(<inductor_name>)Vavg(<output_node>)Davg
Current metadata contract for averaged channels (result.virtual_channel_metadata[...]):
component_type = "averaged_converter"source_component = "averaged_state"domain = "time"- unit:
A,V, orratio
All channel series are sample-aligned with result.time.
Frontend Responsibilities¶
Frontend must:
- expose explicit averaged-mode setup UX for all required mapping fields
- show selected envelope policy (
strict/warn) before running - plot
Iavg(...),Vavg(...),Davgdirectly from backend channels - route channels using metadata first, then canonical names as fallback
- surface typed diagnostics/messages without log regex heuristics
Frontend must not:
- synthesize averaged channels when backend did not emit them
- silently replace averaged mode by switched mode in UI behavior
- infer physical validity outside backend envelope diagnostics
- hide out-of-envelope warnings returned in backend message/diagnostic
Migration From Switched Transient¶
Recommended migration path for control-design iteration:
- Start from a switched converter YAML (
buck,boost, orbuck_boost) that already has mappedVin,L,C,Rload. - Add
simulation.averaged_converterand keepdutyfixed for first parity pass. - Compare averaged-vs-switching with paired benchmark validation.
- Select
operating_mode(ccm,dcm, orauto) based on expected load regime. - Use averaged mode for rapid controller sweeps in supported envelope.
- Keep switched/electrothermal runs as final validation stage.
Reference files:
- switched pair:
benchmarks/circuits/buck_switching_paired.yaml - averaged pair:
benchmarks/circuits/buck_averaged_mvp.yaml - deterministic expected-failure case:
benchmarks/circuits/buck_averaged_expected_failure.yaml
Runnable Examples¶
YAML:
examples/10_buck_averaged_mvp_backend.yaml
Python:
PYTHONPATH=build/python python3 examples/run_buck_averaged_mvp.py
Benchmark subset + KPI gate:
PYTHONPATH=build/python python3 benchmarks/benchmark_runner.py \
--only buck_switching_paired buck_averaged_mvp buck_averaged_expected_failure \
--output-dir benchmarks/phase14_averaged_artifacts/benchmarks
python3 benchmarks/kpi_gate.py \
--baseline benchmarks/kpi_baselines/averaged_converter_phase14_2026-03-07/kpi_baseline.json \
--bench-results benchmarks/phase14_averaged_artifacts/benchmarks/results.json \
--thresholds benchmarks/kpi_thresholds_averaged.yaml \
--report-out benchmarks/phase14_averaged_artifacts/reports/kpi_gate_averaged.json \
--print-report