Skip to content

Commit

Permalink
add capacitor series resistance (sharpie7#937, sharpie7#321)
Browse files Browse the repository at this point in the history
remove hated "capacitor loop with no resistance" error (sharpie7#845, sharpie7#634)
  • Loading branch information
pfalstad committed Nov 29, 2024
1 parent a526d2b commit f45ae50
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 19 deletions.
33 changes: 26 additions & 7 deletions src/com/lushprojects/circuitjs1/client/CapacitorElm.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@

class CapacitorElm extends CircuitElm {
double capacitance;
double compResistance, voltdiff;
double compResistance, voltdiff, seriesResistance;
double initialVoltage;
int capNode2;
Point plate1[], plate2[];
public static final int FLAG_BACK_EULER = 2;
public CapacitorElm(int xx, int yy) {
Expand All @@ -40,6 +41,7 @@ public CapacitorElm(int xa, int ya, int xb, int yb, int f,
initialVoltage = 1e-3;
try {
initialVoltage = new Double(st.nextToken()).doubleValue();
seriesResistance = new Double(st.nextToken()).doubleValue();
} catch (Exception e) {}
}
boolean isTrapezoidal() { return (flags & FLAG_BACK_EULER) == 0; }
Expand All @@ -56,7 +58,7 @@ void shorted() {
}
int getDumpType() { return 'c'; }
String dump() {
return super.dump() + " " + capacitance + " " + voltdiff + " " + initialVoltage;
return super.dump() + " " + capacitance + " " + voltdiff + " " + initialVoltage + " " + seriesResistance;
}

// used for PolarCapacitorElm
Expand Down Expand Up @@ -115,9 +117,16 @@ void stamp() {
// when finding DC operating point, replace cap with a 100M resistor
sim.stampResistor(nodes[0], nodes[1], 1e8);
curSourceValue = 0;
capNode2 = 1;
return;
}

// The capacitor model is between nodes 0 and capNode2. For an
// ideal capacitor, capNode2 is node 1. If series resistance, capNode2 = 2
// and we place a resistor between nodes 2 and 1.
// 2 is an internal node, 0 and 1 are the capacitor terminals.
capNode2 = (seriesResistance > 0) ? 2 : 1;

// capacitor companion model using trapezoidal approximation
// (Norton equivalent) consists of a current source in
// parallel with a resistor. Trapezoidal is more accurate
Expand All @@ -127,9 +136,11 @@ void stamp() {
compResistance = sim.timeStep/(2*capacitance);
else
compResistance = sim.timeStep/capacitance;
sim.stampResistor(nodes[0], nodes[1], compResistance);
sim.stampResistor(nodes[0], nodes[capNode2], compResistance);
sim.stampRightSide(nodes[0]);
sim.stampRightSide(nodes[1]);
sim.stampRightSide(nodes[capNode2]);
if (seriesResistance > 0)
sim.stampResistor(nodes[1], nodes[2], seriesResistance);
}
void startIteration() {
if (isTrapezoidal())
Expand All @@ -139,7 +150,7 @@ void startIteration() {
}

void stepFinished() {
voltdiff = volts[0]-volts[1];
voltdiff = volts[0]-volts[capNode2];
calculateCurrent();
}

Expand All @@ -151,7 +162,7 @@ void setNodeVoltage(int n, double c) {
}

void calculateCurrent() {
double voltdiff = volts[0] - volts[1];
double voltdiff = volts[0] - volts[capNode2];
if (sim.dcAnalysisFlag) {
current = voltdiff/1e8;
return;
Expand All @@ -166,8 +177,9 @@ void calculateCurrent() {
void doStep() {
if (sim.dcAnalysisFlag)
return;
sim.stampCurrentSource(nodes[0], nodes[1], curSourceValue);
sim.stampCurrentSource(nodes[0], nodes[capNode2], curSourceValue);
}
int getInternalNodeCount() { return (!sim.dcAnalysisFlag && seriesResistance > 0) ? 1 : 0; }
void getInfo(String arr[]) {
arr[0] = "capacitor";
getBasicInfo(arr);
Expand All @@ -190,6 +202,8 @@ public EditInfo getEditInfo(int n) {
}
if (n == 2)
return new EditInfo("Initial Voltage (on Reset)", initialVoltage);
if (n == 3)
return new EditInfo("Series Resistance (0 = infinite)", seriesResistance);
// if you add more things here, check PolarCapacitorElm
return null;
}
Expand All @@ -204,8 +218,13 @@ public void setEditValue(int n, EditInfo ei) {
}
if (n == 2)
initialVoltage = ei.value;
if (n == 3)
seriesResistance = ei.value;
}
int getShortcut() { return 'c'; }
public double getCapacitance() { return capacitance; }
public double getSeriesResistance() { return seriesResistance; }
public void setCapacitance(double c) { capacitance = c; }
public void setSeriesResistance(double c) { seriesResistance = c; }
public boolean isIdealCapacitor() { return (seriesResistance == 0); }
}
29 changes: 19 additions & 10 deletions src/com/lushprojects/circuitjs1/client/CirSim.java
Original file line number Diff line number Diff line change
Expand Up @@ -2378,21 +2378,20 @@ boolean validateCircuit() {
}

// look for shorted caps, or caps w/ voltage but no R
if (ce instanceof CapacitorElm) {
if (ce.isIdealCapacitor()) {
FindPathInfo fpi = new FindPathInfo(FindPathInfo.SHORT, ce,
ce.getNode(1));
if (fpi.findPath(ce.getNode(0))) {
console(ce + " shorted");
((CapacitorElm) ce).shorted();
} else {
// a capacitor loop used to cause a matrix error. but we changed the capacitor model
// so it works fine now. The only issue is if a capacitor is added in parallel with
// another capacitor with a nonzero voltage; in that case we will get oscillation unless
// we reset both capacitors to have the same voltage. Rather than check for that, we just
// give an error.
fpi = new FindPathInfo(FindPathInfo.CAP_V, ce, ce.getNode(1));
if (fpi.findPath(ce.getNode(0))) {
stop("Capacitor loop with no resistance!", ce);
// loop of ideal capacitors; set a small series resistance to avoid
// oscillation in case one of them has voltage on it
((CapacitorElm) ce).setSeriesResistance(.1);

// return false to re-stamp the circuit
return false;
}
}
Expand Down Expand Up @@ -2477,10 +2476,20 @@ boolean preStampCircuit() {

// stamp the matrix, meaning populate the matrix as required to simulate the circuit (for all linear elements, at least)
void stampCircuit() {
if (!preStampCircuit())
int i;

// preStampCircuit returns false if there's an error. It can return false if we have capacitor loops
// but we just need to try again in that case. Try again 10 times to avoid infinite loop.
for (i = 0; i != 10; i++)
if (preStampCircuit() || stopMessage != null)
break;
if (stopMessage != null)
return;
if (i == 10) {
stop("failed to stamp circuit", null);
return;
}

int i;
int matrixSize = nodeList.size()-1 + voltageSourceCount;
circuitMatrix = new double[matrixSize][matrixSize];
circuitRightSide = new double[matrixSize];
Expand Down Expand Up @@ -2772,7 +2781,7 @@ boolean checkElm(int n1, CircuitElm ce) {
return false;
if (type == CAP_V) {
// checking for capacitor/voltage source loops
if (!(ce.isWireEquivalent() || ce instanceof CapacitorElm || ce instanceof VoltageElm))
if (!(ce.isWireEquivalent() || ce.isIdealCapacitor() || ce instanceof VoltageElm))
return false;
}
if (n1 == 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/com/lushprojects/circuitjs1/client/CircuitElm.java
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,8 @@ public void setEditValue(int n, EditInfo ei) {}
// is this a wire we can remove?
boolean isRemovableWire() { return false; }

boolean isIdealCapacitor() { return false; }

boolean canViewInScope() { return getPostCount() <= 2; }
boolean comparePair(int x1, int x2, int y1, int y2) {
return ((x1 == y1 && x2 == y2) || (x1 == y2 && x2 == y1));
Expand Down
4 changes: 2 additions & 2 deletions src/com/lushprojects/circuitjs1/client/PolarCapacitorElm.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ void getInfo(String arr[]) {
arr[0] = "capacitor (polarized)";
}
public EditInfo getEditInfo(int n) {
if (n == 3)
if (n == 4)
return new EditInfo("Max Reverse Voltage", maxNegativeVoltage, 0, 0);
return super.getEditInfo(n);
}
public void setEditValue(int n, EditInfo ei) {
if (n == 3 && ei.value >= 0)
if (n == 4 && ei.value >= 0)
maxNegativeVoltage = ei.value;
super.setEditValue(n, ei);
}
Expand Down

0 comments on commit f45ae50

Please sign in to comment.