diff --git a/src/com/lushprojects/circuitjs1/client/SCRElm.java b/src/com/lushprojects/circuitjs1/client/SCRElm.java index 62fb41359..1ba7c3824 100644 --- a/src/com/lushprojects/circuitjs1/client/SCRElm.java +++ b/src/com/lushprojects/circuitjs1/client/SCRElm.java @@ -76,6 +76,7 @@ void reset() { volts[anode] = volts[cnode] = volts[gnode] = 0; diode.reset(); lastvag = lastvac = curcount_a = curcount_c = curcount_g = 0; + state = false; } int getDumpType() { return 177; } @@ -97,6 +98,7 @@ void undumpXml(XMLDeserializer xml) { double ia, ic, ig, curcount_a, curcount_c, curcount_g; double lastvac, lastvag; double gresistance, triggerI, holdingI; + boolean state; final int hs = 8; Polygon poly; @@ -217,6 +219,24 @@ void stamp() { diode.stamp(nodes[inode], nodes[cnode]); } + // Evaluate the on/off state once per timestep, not during Newton-Raphson + // iterations. Previously the state switching was inside doStep(), causing + // the anode resistance to flip-flop between on (0.0105) and off (10e5) on + // every sub-iteration when an external series resistance was present, + // preventing convergence (issue #851). + // + // Use separate trigger/hold conditions with latching, matching the pattern + // used by TriacElm. Once the gate current exceeds triggerI the SCR latches + // on, and stays on until the anode current drops below holdingI. The gate + // only triggers; it does not need to remain driven to keep the SCR on. + void startIteration() { + if (ia < holdingI) + state = false; + if (ig > triggerI) + state = true; + aresistance = state ? .0105 : 10e5; + } + void doStep() { double vac = volts[anode]-volts[cnode]; // typically negative double vag = volts[anode]-volts[gnode]; // typically positive @@ -226,11 +246,6 @@ void doStep() { lastvac = vac; lastvag = vag; diode.doStep(volts[inode]-volts[cnode]); - double icmult = 1/triggerI; - double iamult = 1/holdingI - icmult; - //System.out.println(icmult + " " + iamult); - aresistance = (-icmult*ic + ia*iamult > 1) ? .0105 : 10e5; - //System.out.println(vac + " " + vag + " " + sim.converged + " " + ic + " " + ia + " " + aresistance + " " + volts[inode] + " " + volts[gnode] + " " + volts[anode]); sim.stampResistor(nodes[anode], nodes[inode], aresistance); } void getInfo(String arr[]) {