// ac_plot.java simple AC circuit analysis with plot // java -cp . ac_plot < ac_plot.dat // // Label the circuit nodes consecutively, zero 0 must be ground // Every node must be a part of a current loop and the circuit // must be connected. The input is: // // R i j value_in_ohm resister between node i and node j // C i j value_in_farad capacitor between node i and node j // L i j value_in_henry inductor between node i and node j // I i j value_in_amp current source, flow from node i to node j // V i j value_in_volts value_in_ohms volatge source makes current // A i j a b value_gain voltage i to j times gain is current a to b // F value_in_hertz_initial value_in_hertz_maximum factor // frequency is set to initial value and circuit analyzed, // node voltages are plotted in magnitude and phase in degrees // frequency is multiplied by 'factor' and analysis repeated, // the program exits when frequency is greater than maximum // // A voltage source V must have a series resistor R. This is translated // into two lines I i j value_V/R // R i j value_R node j is positive // The node voltage equations are solved using current. // A value of zero is not allowed for any component. // Solutions may not exists for some circuits at some frequencies. // // Method: Construct admittance matrix Y and current source vector I // Solve system of equations Y*V=I for node voltages V // The subscript zero is never used in the Y matrix, I vector or V vector // I i j V results in I(i)=I(i)-V I(j)=I(j)+V // V i j V1 V2 results in I i j V1/V2 and R i j V2 // R i j V results in Y(i,i)=Y(i,i)+1/V Y(j,j)=Y(j,j)+1/V // Y(i,j)=Y(i,j)-1/v Y(j,i)=Y(j,i)-1/V // C i j V results in YC = (0,2.0*Pi*F*V) complex number // Y(i,i)=Y(i,i)+YC Y(j,j)=Y(j,j)+YC // Y(i,j)=Y(i,j)-YC Y(j,i)=Y(j,i)-YC // L i j V results in YL = (0,-1.0/(2*Pi*F*V)) complex number // Y(i,i)=Y(i,i)+YL Y(j,j)=Y(j,j)+YL // Y(i,j)=Y(i,j)-YL Y(j,i)=Y(j,i)-YL // A a i V results in Y(a,i)=Y(a,i)+V other entries for a,j(-) b,i(-) b,j // The Y matrix must be built for every frequency. // The matrix equation is solved for the node voltages for each frequency. // // If you have frequency omega, divide by 2*Pi for input. Must be Hertz. import java.io.*; import java.awt.*; import java.awt.event.*; public class ac_plot extends Frame { int n; int n_input; // for storing input for various frequencies double F, F_initial, F_final, F_factor, F_range; char type[] = new char[100]; int node1[] = new int[100]; int node2[] = new int[100]; double value[] = new double[100]; Complex i1 = new Complex(0.0,1.0); boolean debug = false; double minmag, maxmag, minang, maxang; double fp[] = new double[129]; // frequency double mp[][] = new double[8][129]; // magnitude double ap[][] = new double[8][129]; // angle int np = 0; Color nodec[] = new Color[8]; ac_plot() { double val, TPIF; Complex cval; int ii, jj; System.out.println("ac_plot running"); setTitle("ac_plot"); setSize(600,600); setBackground(Color.white); setForeground(Color.black); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setVisible(true); nodec[0] = Color.black; nodec[1] = Color.pink; nodec[2] = Color.red; nodec[3] = Color.orange; nodec[4] = Color.yellow; nodec[5] = Color.green; nodec[6] = Color.blue; nodec[7] = Color.gray; System.out.println("ac_plot about to read input"); // no read routine, just fill in circuit data F_initial = 1.0; F_final = 1.0; F_factor = 2.0; n = 0; n_input = 0; try { ReadInput(); } catch(IOException exception) { System.out.println(exception); return; } n_input++; System.out.println("number of nodes="+n+", components="+n_input); if(n==0 || n_input<2) { System.out.println("no recognizable circuit input"); return; } // set up arrays Complex Y[][] = new Complex[n][n]; Complex I[] = new Complex[n]; Complex V[] = new Complex[n]; F = F_initial; while(F<=F_final) { System.out.println("ac_plot about to build Y and I"); TPIF = 6.28*F; // radians per second ComplexMatrix.zero(Y); ComplexMatrix.zero(V); ComplexMatrix.zero(I); for(int i=0; i=0) Y[ii][ii]=Y[ii][ii].add(val); if(jj>=0) Y[jj][jj]=Y[jj][jj].add(val); if(ii>=0 && jj>=0) Y[ii][jj]=Y[ii][jj].subtract(val); if(ii>=0 && jj>=0) Y[jj][ii]=Y[jj][ii].subtract(val); } else if(type[i]=='L' || type[i]=='l') { ii = node1[i]-1; jj = node2[i]-1; cval = (i1.divide(TPIF*value[i])).negate(); if(debug) System.out.println(i+" L "+ii+" "+jj+" "+cval); if(ii>=0) Y[ii][ii]=Y[ii][ii].add(cval); if(jj>=0) Y[jj][jj]=Y[jj][jj].add(cval); if(ii>=0 && jj>=0) Y[ii][jj]=Y[ii][jj].subtract(cval); if(ii>=0 && jj>=0) Y[jj][ii]=Y[jj][ii].subtract(cval); } else if(type[i]=='C' || type[i]=='c') { ii = node1[i]-1; jj = node2[i]-1; cval = i1.multiply(TPIF*value[i]); if(debug) System.out.println(i+" C "+ii+" "+jj+" "+cval); if(ii>=0) Y[ii][ii]=Y[ii][ii].add(cval); if(jj>=0) Y[jj][jj]=Y[jj][jj].add(cval); if(ii>=0 && jj>=0) Y[ii][jj]=Y[ii][jj].subtract(cval); if(ii>=0 && jj>=0) Y[jj][ii]=Y[jj][ii].subtract(cval); } else if(type[i]=='I' || type[i]=='i') { ii = node1[i]-1; jj = node2[i]-1; val = value[i]; if(debug) System.out.println(i+" I "+ii+" "+jj+" "+val); if(ii>=0) I[ii]=I[ii].subtract(val); if(jj>=0) I[jj]=I[jj].add(val); } else if(type[i]=='A' || type[i]=='a') { ii = node1[i]-1; jj = node2[i]-1; val = value[i]; if(debug) System.out.println(i+" A "+ii+" "+jj+" "+val); if(jj>=0 && ii>=0) Y[ii][jj]=Y[ii][jj].add(val); } } if(debug || F==F_initial) { System.out.println("admittance matrix Y"); ComplexMatrix.print(Y); System.out.println("current vector I"); ComplexMatrix.print(I); } ComplexMatrix.solve(Y, I, V); System.out.println("node voltages at frequency = "+F); fp[np] = F; for(int i=0; imaxmag) maxmag=mp[i][np]; if(mp[i][np]maxmag) maxang=ap[i][np]; if(ap[i][np] 180) a = a - 180; if(a< -180) a = a + 180; a = 470 - (110*a)/180; g.fillOval(f-2, m-2, 5, 5); g.fillOval(f-2, a-2, 5, 5); } } for(int i=0; i 180) a = a - 180; if(a< -180) a = a + 180; a = 470 - (110*a)/180; f2 = 50+(int)(530.0*(Math.log(fp[j+1])-logf_initial)/logrange); m2 = 280-(int)(220.0*(mp[i][j+1]-minmag)/(maxmag-minmag)); a2 = (int)(180.0*ap[i][j+1]/Math.PI); if(a2> 180) a2 = a2 - 180; if(a2< -180) a2 = a2 + 180; a2 = 470 - (110*a2)/180; g.drawLine(f, m, f2, m2); g.drawLine(f, a, f2, a2); } } } // end paint void ReadInput() throws IOException // big ugly input method { try { // BufferedReader in = new BufferedReader(new FileReader("bank.dat")); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String input_line; String name; double amount, amount2; int node; int nodev1, nodev2, nodea1, nodea2; int len; int index; int last; if(debug) System.out.println("ReadInput running"); input_line = in.readLine(); // first read before 'while' while(input_line != null) { System.out.println("input: "+input_line); len = input_line.length(); if(len<6) continue; // too short to be a valid input name = input_line.substring(0,1); // type if(debug) System.out.println("name="+name); if(name.equalsIgnoreCase("f")) // 3 frequencies { index = input_line.indexOf(' ',1); // F_initial if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); amount = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount="+amount); F_initial = amount; index = input_line.indexOf(' ',last); // F_final if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); amount = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount="+amount); F_final = amount; index = input_line.indexOf(' ',last); // F_factor if(debug) System.out.println("index="+index); last = len; if(debug) System.out.println("last="+last); amount = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount="+amount); F_factor = amount; if(F_initial<1.0) F_initial=1.0; // log plot of frequency input_line = in.readLine(); // done with this line, read next continue; // go to while loop } if(name.equalsIgnoreCase("a")) // amplifier { index = input_line.indexOf(' ',1); // nodev1 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); nodev1 = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("nodev1="+nodev1); if(nodev1>n) n = nodev1; index = input_line.indexOf(' ',last); // nodev2 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); nodev2 = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("nodev2="+nodev2); if(nodev2>n) n = nodev2; index = input_line.indexOf(' ',last); // nodea1 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); nodea1 = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("nodea1="+nodea1); if(nodea1>n) n = nodea1; index = input_line.indexOf(' ',last); // nodea2 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); nodea2 = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("nodea2="+nodea2); if(nodea2>n) n = nodea2; index = input_line.indexOf(' ',last); // amount if(debug) System.out.println("index="+index); last = len; if(debug) System.out.println("last="+last); amount = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount="+amount); if(nodea1!=0 && nodev1!=0) { n_input++; type[n_input] = 'A'; node1[n_input] = nodea1; node2[n_input] = nodev1; value[n_input] = amount; } if(nodea1!=0 && nodev2!=0) { n_input++; type[n_input] = 'A'; node1[n_input] = nodea1; node2[n_input] = nodev2; value[n_input] = -amount; } if(nodea2!=0 && nodev1!=0) { n_input++; type[n_input] = 'A'; node1[n_input] = nodea2; node2[n_input] = nodev1; value[n_input] = -amount; } if(nodea2!=0 && nodev2!=0) { n_input++; type[n_input] = 'A'; node1[n_input] = nodea2; node2[n_input] = nodev2; value[n_input] = amount; } } if(name.equalsIgnoreCase("v")) // voltage source { index = input_line.indexOf(' ',1); // nodev1 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); nodev1 = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("nodev1="+nodev1); if(nodev1>n) n = nodev1; index = input_line.indexOf(' ',last); // nodev2 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); nodev2 = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("nodev2="+nodev2); if(nodev2>n) n = nodev2; index = input_line.indexOf(' ',last); // amount if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); amount = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount="+amount); index = input_line.indexOf(' ',last); // amount if(debug) System.out.println("index="+index); last = len; if(debug) System.out.println("last="+last); amount2 = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount2="+amount2); n_input++; type[n_input] = 'I'; node1[n_input] = nodev1; node2[n_input] = nodev2; value[n_input] = amount/amount2; n_input++; type[n_input] = 'R'; node1[n_input] = nodev1; node2[n_input] = nodev2; value[n_input] = amount2; } if(name.equalsIgnoreCase("i")) // current source { if(debug) System.out.println("found I"); n_input++; type[n_input] = 'I'; } else if(name.equalsIgnoreCase("r")) // resistor { if(debug) System.out.println("found R"); n_input++; type[n_input] = 'R'; } else if(name.equalsIgnoreCase("c")) // capacitor { if(debug) System.out.println("found C"); n_input++; type[n_input] = 'C'; } else if(name.equalsIgnoreCase("l")) // inductor { if(debug) System.out.println("found L"); n_input++; type[n_input] = 'L'; } else // not recognized { if(debug) System.out.println("unrecognized input"); input_line = in.readLine(); continue; } index = input_line.indexOf(' ',1); // node1 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); node = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("node="+node); if(node>n) n = node; node1[n_input] = node; index = input_line.indexOf(' ',last); // node2 if(debug) System.out.println("index="+index); last = input_line.indexOf(' ',index+1); if(debug) System.out.println("last="+last); node = Integer.parseInt(input_line.substring(index+1,last)); if(debug) System.out.println("node="+node); if(node>n) n = node; node2[n_input] = node; index = input_line.indexOf(' ',last); // amount if(debug) System.out.println("index="+index); last = len; if(debug) System.out.println("last="+last); amount = Double.parseDouble(input_line.substring(index+1,last)); if(debug) System.out.println("amount="+amount); value[n_input] = amount; if(debug) System.out.println(); input_line = in.readLine(); // tested for "null" in 'while' } // end while } // end try catch(IOException exception) { System.out.println(exception); return; } System.out.println("ReadInput finished"); } // end ReadInput public static void main(String args[]) { new ac_plot(); } } // end ac_plot.java