Layer 5 V2.1 — Event detection (iteration to consistency)¶
Layer 5 V2 added auto-commutating diodes but couldn't simulate a boost converter cleanly — the per-step diode logic chattered at the DCM/CCM boundary, and v_sw blew up to 1000+ V during the brief "both switches OFF" dead-time at startup.
Layer 5 V2.1 fixes this by iterating the switch state to consistency at each step:
- Solve with the current mask.
- Check if any diode would flip (
diodes.update_from_state). - If yes, re-solve with the new mask.
- Repeat until stable OR
max_event_iterationsis hit. - Record the sample.
This is the V0 of event detection — a fixed-point iteration on switch state. Sub-step bisection (finding the exact mid-step commutation time) is a future enhancement; the current loop is "single events per step at full dt accuracy".
Result: boost converter passes¶
| Metric | Analytical | Numerical | Error |
|---|---|---|---|
| mean V_out | 24.0 V | 24.014 V | 0.06 % |
| mean I_L | 2.40 A | 2.327 A | 3.0 % |
| Wall clock | < 30 s | 1.2 s | — |
| max iterations | ≤ 4 | 1 | — |
Only 1 extra solve was needed at each commutation moment
(1999 of 100k steps), so the overhead is ~2 %. Per-step cost
still dominated by the cached triangular solve.
API changes (additive)¶
struct SimulationOptions {
// ... existing fields ...
Size max_event_iterations = 16; // NEW (default 16)
};
struct SimulationResult {
// ... existing fields ...
std::vector<Size> event_iteration_count; // NEW
};
max_event_iterations = 0 disables iteration (matches V2
behaviour, useful for regression testing).
event_iteration_count[k] is the count of EXTRA solves at step
k (0 = first solve was consistent).
What V2.1 fixes that V2 couldn't¶
The boost converter at startup goes through several scenarios: - Q ON, D OFF: L charges. Clean. - Q OFF, D ON (CCM): L discharges into the cap. Clean. - Q OFF, D OFF (DCM dead-time): i_L → 0, both switches open, v_sw is unbounded (only g_off paths). This is the bad case.
V2's per-step decision saw v_sw blowing up to 1000+ V → forced the diode ON for the NEXT step. But the current step already had bogus values that corrupted the L's history.
V2.1's iteration loop catches this WITHIN the step: - Solve with [Q=OFF, D=OFF]. v_sw goes huge → diode flips. - Solve with [Q=OFF, D=ON]. v_sw clamps, i_L flows correctly. - update_from_state confirms diode stays ON. - Record the GOOD sample.
Limitations (V0 of event-detection)¶
- No sub-step accuracy. Events get caught WITHIN a step; the exact crossing time isn't bisected. For typical PE workloads at dt = T_sw/100, the error is < 1 % of a switching period — negligible.
- One commutation per device per step max. If two events really need to happen mid-step, the iteration will resolve them sequentially (or hit the limit and throw).
- Iteration cost. Each commutation costs ~1 extra triangular solve (~1 µs in Debug). For 100k-step simulations with 2k commutations, total overhead ~2 %.
Status¶
| Layer | Cases | Assertions |
|---|---|---|
| 0 | 19 | 80 |
| 1 | 36 | 126 |
| 2 | 36 | 93 |
| 3 | 16 | 61 |
| 4 V0 | 24 | 58 |
| 5 V0 | 21 | 2069 |
| 4 V1 | 32 | 76 |
| 5 V1 | 17 | 59 |
| 5 V2.1 | 18 | 42 ← boost re-enabled |
| Total | 219 | 2664 |
v1 regression: 304 cases / 4214 assertions, all green.