/*
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 TappedTransformerElm extends CircuitElm {
double inductance, ratio;
Point ptEnds[], ptCoil[], ptCore[];
double current[], curcount[];
public TappedTransformerElm(int xx, int yy) {
super(xx, yy);
inductance = 4;
ratio = 1;
noDiagonal = true;
current = new double[4];
curcount = new double[4];
voltdiff = new double[3];
curSourceValue = new double[3];
a = new double[9];
}
public TappedTransformerElm(int xa, int ya, int xb, int yb, int f,
StringTokenizer st) {
super(xa, ya, xb, yb, f);
inductance = new Double(st.nextToken()).doubleValue();
ratio = new Double(st.nextToken()).doubleValue();
current = new double[4];
curcount = new double[4];
current[0] = new Double(st.nextToken()).doubleValue();
current[1] = new Double(st.nextToken()).doubleValue();
try {
current[2] = new Double(st.nextToken()).doubleValue();
} catch (Exception e) { }
voltdiff = new double[3];
curSourceValue = new double[3];
noDiagonal = true;
a = new double[9];
}
int getDumpType() { return 169; }
String dump() {
return super.dump() + " " + inductance + " " + ratio + " " +
current[0] + " " + current[1] + " " + current[2];
}
void draw(Graphics g) {
int i;
for (i = 0; i != 5; i++) {
setVoltageColor(g, volts[i]);
drawThickLine(g, ptEnds[i], ptCoil[i]);
}
for (i = 0; i != 4; i++) {
if (i == 1)
continue;
setPowerColor(g, current[i]*(volts[i]-volts[i+1]));
drawCoil(g, i > 1 ? -6 : 6,
ptCoil[i], ptCoil[i+1], volts[i], volts[i+1]);
}
g.setColor(needsHighlight() ? selectColor : lightGrayColor);
for (i = 0; i != 4; i += 2) {
drawThickLine(g, ptCore[i], ptCore[i+1]);
}
// calc current of tap wire
current[3] = current[1]-current[2];
for (i = 0; i != 4; i++)
curcount[i] = updateDotCount(current[i], curcount[i]);
// primary dots
drawDots(g, ptEnds[0], ptCoil[0], curcount[0]);
drawDots(g, ptCoil[0], ptCoil[1], curcount[0]);
drawDots(g, ptCoil[1], ptEnds[1], curcount[0]);
// secondary dots
drawDots(g, ptEnds[2], ptCoil[2], curcount[1]);
drawDots(g, ptCoil[2], ptCoil[3], curcount[1]);
drawDots(g, ptCoil[3], ptEnds[3], curcount[3]);
drawDots(g, ptCoil[3], ptCoil[4], curcount[2]);
drawDots(g, ptCoil[4], ptEnds[4], curcount[2]);
drawPosts(g);
setBbox(ptEnds[0], ptEnds[4], 0);
}
void setPoints() {
super.setPoints();
int hs = 32;
ptEnds = newPointArray(5);
ptCoil = newPointArray(5);
ptCore = newPointArray(4);
ptEnds[0] = point1;
ptEnds[2] = point2;
interpPoint(point1, point2, ptEnds[1], 0, -hs*2);
interpPoint(point1, point2, ptEnds[3], 1, -hs);
interpPoint(point1, point2, ptEnds[4], 1, -hs*2);
double ce = .5-12/dn;
double cd = .5-2/dn;
int i;
interpPoint(ptEnds[0], ptEnds[2], ptCoil[0], ce);
interpPoint(ptEnds[0], ptEnds[2], ptCoil[1], ce, -hs*2);
interpPoint(ptEnds[0], ptEnds[2], ptCoil[2], 1-ce);
interpPoint(ptEnds[0], ptEnds[2], ptCoil[3], 1-ce, -hs);
interpPoint(ptEnds[0], ptEnds[2], ptCoil[4], 1-ce, -hs*2);
for (i = 0; i != 2; i++) {
int b = -hs*i*2;
interpPoint(ptEnds[0], ptEnds[2], ptCore[i], cd, b);
interpPoint(ptEnds[0], ptEnds[2], ptCore[i+2], 1-cd, b);
}
}
Point getPost(int n) {
return ptEnds[n];
}
int getPostCount() { return 5; }
void reset() {
current[0] = current[1] = current[2] = volts[0] = volts[1] = volts[2] =
volts[3] = volts[4] = curcount[0] = curcount[1] = curcount[2] = 0;
}
double a[];
void stamp() {
// equations for transformer:
// v1 = L1 di1/dt + M1 di2/dt + M1 di3/dt
// v2 = M1 di1/dt + L2 di2/dt + M2 di3/dt
// v3 = M1 di1/dt + M2 di2/dt + L2 di3/dt
// we invert that to get:
// di1/dt = a1 v1 + a2 v2 + a3 v3
// di2/dt = a4 v1 + a5 v2 + a6 v3
// di3/dt = a7 v1 + a8 v2 + a9 v3
// integrate di1/dt using trapezoidal approx and we get:
// i1(t2) = i1(t1) + dt/2 (i1(t1) + i1(t2))
// = i1(t1) + a1 dt/2 v1(t1)+a2 dt/2 v2(t1)+a3 dt/2 v3(t3) +
// a1 dt/2 v1(t2)+a2 dt/2 v2(t2)+a3 dt/2 v3(t3)
// the norton equivalent of this for i1 is:
// a. current source, I = i1(t1) + a1 dt/2 v1(t1) + a2 dt/2 v2(t1)
// + a3 dt/2 v3(t1)
// b. resistor, G = a1 dt/2
// c. current source controlled by voltage v2, G = a2 dt/2
// d. current source controlled by voltage v3, G = a3 dt/2
// and similarly for i2
//
// first winding goes from node 0 to 1, second is from 2 to 3 to 4
double l1 = inductance;
// second winding is split in half, so each part has half the turns;
// we square the 1/2 to divide by 4
double l2 = inductance*ratio*ratio/4;
double cc = .99;
double m1 = cc*Math.sqrt(l1*l2);
// mutual inductance between two halves of the second winding
// is equal to self-inductance of either half (slightly less
// because the coupling is not perfect)
double m2 = cc*l2;
// load pre-inverted matrix
a[0] = l2+m2;
a[1] = a[2] = a[3] = a[6] = -m1;
a[4] = a[8] = (l1*l2-m1*m1)/(l2-m2);
a[5] = a[7] = (m1*m1-l1*m2)/(l2-m2);
int i;
double det = l1*(l2+m2)-2*m1*m1;
for (i = 0; i != 9; i++)
a[i] *= (isTrapezoidal() ? sim.timeStep/2 : sim.timeStep)/det;
sim.stampConductance(nodes[0], nodes[1], a[0]);
sim.stampVCCurrentSource(nodes[0], nodes[1], nodes[2], nodes[3], a[1]);
sim.stampVCCurrentSource(nodes[0], nodes[1], nodes[3], nodes[4], a[2]);
sim.stampVCCurrentSource(nodes[2], nodes[3], nodes[0], nodes[1], a[3]);
sim.stampConductance (nodes[2], nodes[3], a[4]);
sim.stampVCCurrentSource(nodes[2], nodes[3], nodes[3], nodes[4], a[5]);
sim.stampVCCurrentSource(nodes[3], nodes[4], nodes[0], nodes[1], a[6]);
sim.stampVCCurrentSource(nodes[3], nodes[4], nodes[2], nodes[3], a[7]);
sim.stampConductance (nodes[3], nodes[4], a[8]);
for (i = 0; i != 5; i++)
sim.stampRightSide(nodes[i]);
}
boolean isTrapezoidal() { return true; }
void startIteration() {
voltdiff[0] = volts[0]-volts[1];
voltdiff[1] = volts[2]-volts[3];
voltdiff[2] = volts[3]-volts[4];
int i, j;
for (i = 0; i != 3; i++) {
curSourceValue[i] = current[i];
if (isTrapezoidal())
for (j = 0; j != 3; j++)
curSourceValue[i] += a[i*3+j]*voltdiff[j];
}
}
double curSourceValue[], voltdiff[];
void doStep() {
sim.stampCurrentSource(nodes[0], nodes[1], curSourceValue[0]);
sim.stampCurrentSource(nodes[2], nodes[3], curSourceValue[1]);
sim.stampCurrentSource(nodes[3], nodes[4], curSourceValue[2]);
}
void calculateCurrent() {
voltdiff[0] = volts[0]-volts[1];
voltdiff[1] = volts[2]-volts[3];
voltdiff[2] = volts[3]-volts[4];
int i, j;
for (i = 0; i != 3; i++) {
current[i] = curSourceValue[i];
for (j = 0; j != 3; j++)
current[i] += a[i*3+j]*voltdiff[j];
}
}
void getInfo(String arr[]) {
arr[0] = "transformer";
arr[1] = "L = " + getUnitText(inductance, "H");
arr[2] = "Ratio = " + ratio;
//arr[3] = "I1 = " + getCurrentText(current1);
arr[3] = "Vd1 = " + getVoltageText(volts[0]-volts[2]);
//arr[5] = "I2 = " + getCurrentText(current2);
arr[4] = "Vd2 = " + getVoltageText(volts[1]-volts[3]);
}
@Override double getCurrentIntoPoint(int xa, int ya) {
if (xa == ptEnds[0].x && ya == ptEnds[0].y)
return -current[0];
if (xa == ptEnds[1].x && ya == ptEnds[1].y)
return current[0];
if (xa == ptEnds[2].x && ya == ptEnds[2].y)
return -current[1];
if (xa == ptEnds[3].x && ya == ptEnds[3].y)
return current[3];
return current[2];
}
boolean getConnection(int n1, int n2) {
if (comparePair(n1, n2, 0, 1))
return true;
if (comparePair(n1, n2, 2, 3))
return true;
if (comparePair(n1, n2, 3, 4))
return true;
if (comparePair(n1, n2, 2, 4))
return true;
return false;
}
public EditInfo getEditInfo(int n) {
if (n == 0)
return new EditInfo("Primary Inductance (H)", inductance, .01, 5);
if (n == 1)
return new EditInfo("Ratio", ratio, 1, 10).setDimensionless();
return null;
}
public void setEditValue(int n, EditInfo ei) {
if (n == 0)
inductance = ei.value;
if (n == 1)
ratio = ei.value;
}
}