/*
Copyright (C) Paul Falstad
This file is part of CircuitJS1.
CircuitJS1 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
CircuitJS1 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CircuitJS1. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lushprojects.circuitjs1.client;
//import java.awt.*;
//import java.util.StringTokenizer;
class VCVSElm extends VCCSElm {
public VCVSElm(int xa, int ya, int xb, int yb, int f,
StringTokenizer st) {
super(xa, ya, xb, yb, f, st);
// inputCount = Integer.parseInt(st.nextToken());
// exprString = CustomLogicModel.unescape(st.nextToken());
// parseExpr();
// setupPins();
}
public VCVSElm(int xx, int yy) {
super(xx, yy);
exprString = "2*(a-b)";
// inputCount = 2;
// exprString = "a+b";
// parseExpr();
// setupPins();
}
void setupPins() {
sizeX = 2;
sizeY = inputCount > 2 ? inputCount : 2;
pins = new Pin[inputCount+2];
int i;
for (i = 0; i != inputCount; i++)
pins[i] = new Pin(i, SIDE_W, Character.toString((char)('A'+i)));
pins[inputCount] = new Pin(0, SIDE_E, "V+");
pins[inputCount].output = true;
pins[inputCount+1] = new Pin(1, SIDE_E, "V-");
lastVolts = new double[inputCount];
exprState = new ExprState(inputCount);
}
String getChipName() { return "VCVS"; }
void stamp() {
int vn = pins[inputCount].voltSource + sim.nodeList.size();
sim.stampNonLinear(vn);
sim.stampVoltageSource(nodes[inputCount+1], nodes[inputCount], pins[inputCount].voltSource);
}
void doStep() {
int i;
// converged yet?
double limitStep = getLimitStep();
double convergeLimit = getConvergeLimit();
for (i = 0; i != inputCount; i++) {
if (Math.abs(volts[i]-lastVolts[i]) > convergeLimit)
sim.converged = false;
if (Double.isNaN(volts[i]))
volts[i] = 0;
if (Math.abs(volts[i]-lastVolts[i]) > limitStep)
volts[i] = lastVolts[i] + sign(volts[i]-lastVolts[i], limitStep);
}
int vn = pins[inputCount].voltSource + sim.nodeList.size();
if (expr != null) {
// calculate output
for (i = 0; i != inputCount; i++)
exprState.values[i] = volts[i];
exprState.t = sim.t;
double v0 = expr.eval(exprState);
if (Math.abs(volts[inputCount]-volts[inputCount+1]-v0) > Math.abs(v0)*.01 && sim.subIterations < 100)
sim.converged = false;
double rs = v0;
// calculate and stamp output derivatives
for (i = 0; i != inputCount; i++) {
double dv = 1e-6;
exprState.values[i] = volts[i]+dv;
double v = expr.eval(exprState);
exprState.values[i] = volts[i]-dv;
double v2 = expr.eval(exprState);
double dx = (v-v2)/(dv*2);
if (Math.abs(dx) < 1e-6)
dx = sign(dx, 1e-6);
// sim.console("cae_ " + i + " " + dx);
sim.stampMatrix(vn, nodes[i], -dx);
// adjust right side
rs -= dx*volts[i];
exprState.values[i] = volts[i];
}
sim.stampRightSide(vn, rs);
}
for (i = 0; i != inputCount; i++)
lastVolts[i] = volts[i];
}
int getPostCount() { return inputCount+2; }
int getVoltageSourceCount() { return 1; }
int getDumpType() { return 212; }
boolean hasCurrentOutput() { return false; }
void setCurrent(int vn, double c) {
if (pins[inputCount].voltSource == vn) {
pins[inputCount].current = c;
pins[inputCount+1].current = -c;
}
}
}