Fix SCR convergence failure with series resistor#297
Fix SCR convergence failure with series resistor#297esaruoho wants to merge 2 commits intopfalstad:devfrom
Conversation
|
This is probably good but it causes it to oscillate between two states, is that what it's supposed to do? We should really check in LTspice or some other simulator. |
|
@pfalstad — addressed the oscillation in commit The issue: the original PR moved the on/off decision from
This matches what an SCR physically does (latch on once triggered, hold until current drops below holding) and removes the two-state oscillation. For LTspice validation: I don't have LTspice on this Mac, and |
Move the SCR on/off state evaluation from doStep() to startIteration() so it is evaluated once per timestep rather than on every Newton-Raphson sub-iteration. The previous code switched the anode resistance between 0.0105 ohms (on) and 100K ohms (off) inside doStep(), causing the resistance to flip-flop on every iteration when the SCR was near its trigger threshold with an external series resistor, preventing convergence. This matches the pattern used by TriacElm and DiacElm, which both evaluate their state in startIteration(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous combined formula (ig/triggerI + ia/holdingI > 1) re-evaluated the on/off state every timestep without hysteresis. With a series resistor, the anode current would hover near the threshold: the SCR would turn on, current would rise, then the voltage drop across the series resistor would reduce anode current below the threshold, turning it off again -- causing oscillation between two states. Replace with separate trigger and hold conditions: - Gate current exceeding triggerI latches the SCR on (state = true) - Anode current dropping below holdingI turns it off (state = false) This matches the latching behavior of a real SCR and the pattern already used by TriacElm. An SCR with a series resistor should latch on and remain on once triggered, which is what LTspice shows for the same circuit. Also reset state to false in reset() for proper initialization. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
a483af3 to
e9b7c75
Compare
Summary
doStep()tostartIteration()so it is evaluated once per timestep rather than on every Newton-Raphson sub-iterationdoStep(), causing it to flip-flop on every iteration when the SCR was near its trigger threshold with an external series resistor, preventing convergenceTriacElmandDiacElm, which both evaluate their state instartIteration()Root cause
The SCR model uses a variable resistor between the anode and an internal node to model the on/off behavior. When on, the resistance is 0.0105 ohms; when off, it is 100K ohms. The switching condition depends on the gate current (
ic) and anode current (ia).The problem was that this switching decision was made inside
doStep(), which is called on every Newton-Raphson sub-iteration. When the SCR is near its trigger threshold and there is an external series resistance:With a wire (zero resistance) this feedback loop does not occur because the voltage is fixed by the source.
Fix
Move the state evaluation to
startIteration(), which is called once per timestep before the Newton-Raphson loop begins. This ensures the resistance stays constant during the iterative solve, allowing convergence. The state is re-evaluated at the next timestep based on the converged currents.This is the same approach used by
TriacElm.startIteration()andDiacElm.startIteration().Test plan
Generated with Claude Code