/*
Copyright (C) Paul Falstad and Iain Sharp
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 TriodeElm extends CircuitElm {
double mu, kg1;
double curcountp, curcountc, curcountg, currentp, currentg, currentc;
final double gridCurrentR = 6000;
public TriodeElm(int xx, int yy) {
super(xx, yy);
mu = 93;
kg1 = 680;
setup();
}
public TriodeElm(int xa, int ya, int xb, int yb, int f,
StringTokenizer st) {
super(xa, ya, xb, yb, f);
mu = new Double(st.nextToken()).doubleValue();
kg1 = new Double(st.nextToken()).doubleValue();
setup();
}
void setup() {
noDiagonal = true;
}
boolean nonLinear() { return true; }
void reset() {
volts[0] = volts[1] = volts[2] = 0;
curcount = 0;
}
String dump() {
return super.dump() + " " + mu + " " + kg1;
}
int getDumpType() { return 173; }
Point plate[], grid[], cath[], midgrid, midcath;
int circler;
void setPoints() {
super.setPoints();
plate = newPointArray(4);
grid = newPointArray(8);
cath = newPointArray(4);
grid[0] = point1;
int nearw = 8;
interpPoint(point1, point2, plate[1], 1, nearw);
int farw = 32;
interpPoint(point1, point2, plate[0], 1, farw);
int platew = 18;
interpPoint2(point2, plate[1], plate[2], plate[3], 1, platew);
circler = 24;
interpPoint(point1, point2, grid[1], (dn-circler)/dn, 0);
int i;
for (i = 0; i != 3; i++) {
interpPoint(grid[1], point2, grid[2+i*2], (i*3+1)/4.5, 0);
interpPoint(grid[1], point2, grid[3+i*2], (i*3+2)/4.5, 0);
}
midgrid = point2;
int cathw = 16;
midcath = interpPoint(point1, point2, 1, -nearw);
interpPoint2(point2, plate[1], cath[1], cath[2], -1, cathw);
interpPoint(point2, plate[1], cath[3], -1.2, -cathw);
interpPoint(point2, plate[1], cath[0], -farw/(double) nearw, cathw);
}
void draw(Graphics g) {
g.setColor(Color.gray);
drawThickCircle(g, point2.x, point2.y, circler);
setBbox(point1, plate[0], 16);
adjustBbox(cath[0].x, cath[1].y, point2.x+circler, point2.y+circler);
setPowerColor(g, true);
// draw plate
setVoltageColor(g, volts[0]);
drawThickLine(g, plate[0], plate[1]);
drawThickLine(g, plate[2], plate[3]);
// draw grid
setVoltageColor(g, volts[1]);
int i;
for (i = 0; i != 8; i += 2)
drawThickLine(g, grid[i], grid[i+1]);
// draw cathode
setVoltageColor(g, volts[2]);
for (i = 0; i != 3; i++)
drawThickLine(g, cath[i], cath[i+1]);
// draw dots
curcountp = updateDotCount(currentp, curcountp);
curcountc = updateDotCount(currentc, curcountc);
curcountg = updateDotCount(currentg, curcountg);
if (sim.dragElm != this) {
drawDots(g, plate[0], midgrid, curcountp);
drawDots(g, midgrid, midcath, curcountc);
drawDots(g, midcath, cath[1], curcountc+8);
drawDots(g, cath[1], cath[0], curcountc+8);
drawDots(g, point1, midgrid, curcountg);
}
drawPosts(g);
}
double getCurrentIntoPoint(int xa, int ya) {
if (xa == cath[0].x && ya == cath[0].y)
return currentc;
if (xa == plate[0].x && ya == plate[0].y)
return -currentp;
return -currentg;
}
Point getPost(int n) {
return (n == 0) ? plate[0] : (n == 1) ? grid[0] : cath[0];
}
int getPostCount() { return 3; }
double getPower() { return (volts[0]-volts[2])*current; }
double lastv0, lastv1, lastv2;
void doStep() {
double vs[] = new double[3];
vs[0] = volts[0];
vs[1] = volts[1];
vs[2] = volts[2];
if (vs[1] > lastv1 + .5)
vs[1] = lastv1 + .5;
if (vs[1] < lastv1 - .5)
vs[1] = lastv1 - .5;
if (vs[2] > lastv2 + .5)
vs[2] = lastv2 + .5;
if (vs[2] < lastv2 - .5)
vs[2] = lastv2 - .5;
int grid = 1;
int cath = 2;
int plate = 0;
double vgk = vs[grid] -vs[cath];
double vpk = vs[plate]-vs[cath];
if (Math.abs(lastv0-vs[0]) > .01 ||
Math.abs(lastv1-vs[1]) > .01 ||
Math.abs(lastv2-vs[2]) > .01)
sim.converged = false;
lastv0 = vs[0];
lastv1 = vs[1];
lastv2 = vs[2];
double ids = 0;
double gm = 0;
double Gds = 0;
double ival = vgk+vpk/mu;
currentg = 0;
if (vgk > .01) {
sim.stampResistor(nodes[grid], nodes[cath], gridCurrentR);
currentg = vgk/gridCurrentR;
}
if (ival < 0) {
// should be all zero, but that causes a singular matrix,
// so instead we treat it as a large resistor
Gds = 1e-8;
ids = vpk*Gds;
} else {
ids = Math.pow(ival, 1.5)/kg1;
double q = 1.5*Math.sqrt(ival)/kg1;
// gm = dids/dgk;
// Gds = dids/dpk;
Gds = q;
gm = q/mu;
}
currentp = ids;
currentc = ids+currentg;
double rs = -ids + Gds*vpk + gm*vgk;
sim.stampMatrix(nodes[plate], nodes[plate], Gds);
sim.stampMatrix(nodes[plate], nodes[cath], -Gds-gm);
sim.stampMatrix(nodes[plate], nodes[grid], gm);
sim.stampMatrix(nodes[cath], nodes[plate], -Gds);
sim.stampMatrix(nodes[cath], nodes[cath], Gds+gm);
sim.stampMatrix(nodes[cath], nodes[grid], -gm);
sim.stampRightSide(nodes[plate], rs);
sim.stampRightSide(nodes[cath ], -rs);
}
void stamp() {
sim.stampNonLinear(nodes[0]);
sim.stampNonLinear(nodes[1]);
sim.stampNonLinear(nodes[2]);
}
void getInfo(String arr[]) {
arr[0] = "triode";
double vbc = volts[0]-volts[1];
double vbe = volts[0]-volts[2];
double vce = volts[1]-volts[2];
arr[1] = "Vbe = " + getVoltageText(vbe);
arr[2] = "Vbc = " + getVoltageText(vbc);
arr[3] = "Vce = " + getVoltageText(vce);
}
// grid not connected to other terminals
boolean getConnection(int n1, int n2) { return !(n1 == 1 || n2 == 1); }
public EditInfo getEditInfo(int n) {
if (n == 0)
return new EditInfo("mu", mu, 0, 0).setDimensionless();
if (n == 1)
return new EditInfo("kg1", kg1, 0, 0).setDimensionless();
return null;
}
public void setEditValue(int n, EditInfo ei) {
if (n == 0 && ei.value > 0)
mu = ei.value;
if (n == 1 && ei.value > 0)
kg1 = ei.value;
}
}