C--------------------------------------------------------------------------------- C AC.FOR - Alternating Current electronic circuit analysis program - ver 05/14/06 C STEP 1 - draw the circuit, number nodes consecutively, type up data in notepad. C STEP 2 - run AC.exe which asks for an input file name. C STEP 3 - view the output results which are displayed automatically in file OP. C--------------------------------------------------------------------------------- C Y(*,*) is the circuit admittance matrix with the driving vector in NN+1 column. C NN is the number of nodes. Nodes are numbered from 1 to NN (no gaps) and C ground is given as node 0. Elements can be paralleled between the nodes. C Descriptions of the data are given below for each type of data that is read. C--------------------------------------------------------------------------------- DIMENSION NF(51),NT(51),V1(51),V2(51) sets up arrays NF NT V1 V2 from node, to node, voltages COMPLEX Y(30,31),YIK,YKK sets up complex number array Y and scalars YIK and YKK CHARACTER*101 YAX,YBX,YCX,TP(51)*2,AX*2,ERR*32,FIN*32,C132*132 sets up character variables defaulting to 101 characters except where specified C open the text output report file named OP ERR='CANNOT OPEN FILE OP' OPEN(6,FILE='OP',ERR=97) opens file 6 which is named OP C open the input data file WRITE(*,*) 'ENTER THE INPUT DATA FILE NAME' write to the screen what is in the quotation marks READ(*,*) FIN read from the keyboard FIN which is the input file name ERR='CANNOT OPEN '//FIN OPEN(5,FILE=FIN,STATUS='OLD',ERR=98) open the input file named FIN WRITE(6,'(A6,A32/)') 'FILE: ',FIN write to the output file OP the name of the input file C the first line of data contains the following parameters lines with C are comment statements, which fortran ignores C AX = BO (Bode plot), LO for log F - lin V plot, LI for lin F -lin V plot, TA for tabulations C NG = the node number to graph (not used for tabulation output) C NL = number of lines to graph (line 0 is also assumed) C YM = Y axis magnitude in volts (for AX=LI) or decibels (for AX=LO) C FI = initial frequency in Hz C FF = final frequency in Hz ERR='ERROR ON THE FIRST LINE OF DATA' 14 READ(5,'(A132)',END=98) C132 read the input file FIN a 132 character string into varable C132 WRITE(6,'(A132)') C132 C an * in column 1 means it is a comment line and is ignored, comments can be added after data also IF(C132(1:1).EQ.'*') GOTO 14 see if the first character of C132 is an * character and if so go back and read another line READ(C132,*,ERR=98,END=98) AX,NG,NL,YM,FI,FF read the rest of C132 for numbers and put those numbers in AX NG NL YM FI and FF C NE is the number of circuit elements NE=0 C NN is the number of nodes, 0=ground and there are no gaps in the numbers used NN=0 C read all the circuit data: TP=type, NF=from node, NT=to node, V1 and V2 are two circuit values 1 N=NE+1 add 1 to NE and store the result in N ERR='ERROR READING DATA' initialize the ERR character string IF(N.EQ.1) ERR=ERR(1:18)//' ON 2nd LINE' append to the first 18 characters of ERR what is in the quotation marks IF(N.GT.1) ERR=ERR(1:18)//' AFTER '//TP(N-1) do the same as above 6 READ(5,'(A132)',END=2,ERR=98) C132 read another line of the FIN file into the character array WRITE(6,'(A132)') C132 echo that line on the output file OP IF(C132(1:1).EQ.'*') GOTO 6 if there is a * in the first column the go back and read another line of data READ(C132,*,END=2,ERR=98) TP(N),NF(N),NT(N),V1(N),V2(N) read C132 numbers into the variables listed such as TP NF NT V1 V2 ERR='MAXIMUM OF 50 LINES IS EXCEEDED' IF(N.GE.51) GOTO 98 ERR='FROM NODE = TO NODE' IF(NF(N).EQ.NT(N)) GOTO 98 ERR='NEGATIVE NODE NUMBER' IF(NF(N).LT.0.OR.NT(N).LT.0) GOTO 98 IF(NF(N).GT.NN) NN=NF(N) IF(NT(N).GT.NN) NN=NT(N) ERR='MAXIMUM OF 30 NODES IS EXCEEDED' IF(NN.GE.31) GOTO 98 NE=N GOTO 1 C initialize and print the Y axis of the graph 2 YAX='I---------I---------I---------I---------I---------'// & 'I---------I---------I---------I---------I---------I' YBX='+ + + + + '// & '+ + + + + +' IF(AX.EQ.'LO'.OR.AX.EQ.'LI') THEN WRITE(6,'(/14X,1H0,F13.3,8F10.3)') (YM*I/9.,I=1,9) WRITE(6,'(4X,A128)') YAX//' FREQUENCY VOLTS PHASE' ENDIF IF(AX.EQ.'BO') THEN WRITE(6,'(/F6.1,10F10.1)') (YM*I/5.,I=-5,5) WRITE(6,'(4X,A128)') YAX//' FREQUENCY dB PHASE' ENDIF IF(AX.EQ.'TA') WRITE(6,FMT='('' TABULAR DATA'')') IF(NL.LT.1) NL=1 C let IAX represent either the linear (IAX=0) or log (IAX=1) frequency axis IAX=0 IF(AX.EQ.'BO'.OR.AX.EQ.'LO') IAX=1 C---------------------------------------------------------------------- C begin frequency loop - build and solve matrix for each frequency C---------------------------------------------------------------------- PI=3.14159265 DO 30 N=0,NL begin a loop through statement 30 incrementing N = 0 1 2 ... NL C linear delta frequency used for AX=TA and AX=LI IF(IAX.EQ.0) THEN if IAX = 0, do the statements down through the ENDIF, otherwise skip these statements and pick up below the ENDIF in either case F=((FF-FI)/NL)*N+FI evaluate inside parentheses first, then start on right end and calculate going to the left and put answer in F ERR='NEGATIVE FREQUENCY ERROR' IF(F.LT.0.) GOTO 98 if L < 0 go to statement 98 ENDIF C log delta frequency used for AX=BO and AX=LO IF(IAX.EQ.1) THEN ERR='ZERO HZ ON LOG SCALE' IF(FI.LE.0..OR.FF.LE.0.) GOTO 98 F=FI*10.**(N*ALOG(FF/FI)/ALOG(10.)/NL) ENDIF W=2.*PI*F C NA is the column of the Augmented independent vector on the far right of the Y matrix NA=NN+1 C reset the Y matrix to zero DO 3 I=1,NN here is a double loop, J = 1 2 3 ... NA for each I = 1 2 3 ... NN DO 3 J=1,NA 3 Y(I,J)=0. end of loop and set each Y(I,J) to 0. C add each Kth circuit element to the Y admittance matrix (NE = number of elements) K=0 4 K=K+1 IF(K.GT.NE) GOTO 5 I=NF(K) J=NT(K) C add an independent current source V1 amps at angle of V2 degrees IF(TP(K).EQ.'IS') THEN if TP(K)='IS' then do all the steps through the ENDIF V1R=V1(K)*COS(V2(K)*PI/180.) V1X=V1(K)*SIN(V2(K)*PI/180.) IF(I.GT.0) Y(I,NA)=Y(I,NA)+CMPLX(V1R,V1X) IF(J.GT.0) Y(J,NA)=Y(J,NA)-CMPLX(V1R,V1X) GOTO 4 ENDIF C add an independent voltage source V1 volts at an angle of V2 degrees IF(TP(K).EQ.'VS') THEN V1R=V1(K)*COS(V2(K)*PI/180.)*1.E12 V1X=V1(K)*SIN(V2(K)*PI/180.)*1.E12 IF(I.GT.0) Y(I,NA)=Y(I,NA)+CMPLX(V1R,V1X) IF(J.GT.0) Y(J,NA)=Y(J,NA)-CMPLX(V1R,V1X) IF(I.GT.0) Y(I,I)=Y(I,I)+1.E12 IF(J.GT.0) Y(J,J)=Y(J,J)+1.E12 IF(I.GT.0.AND.J.GT.0) THEN Y(I,J)=Y(I,J)-1.E12 Y(J,I)=Y(J,I)-1.E12 ENDIF GOTO 4 ENDIF C add series RC element IF(TP(K).EQ.'RC') THEN YKK=0. IF(ABS(V2(K)).LE.0.) THEN IF(ABS(V1(K)).GT.0.) YKK=1./V1(K) ELSE IF(ABS(W).LE.0.) GOTO 4 YKK=1.D0/CMPLX(V1(K),-1./(W*V2(K))) ENDIF IF(I.GT.0) Y(I,I)=Y(I,I)+YKK IF(J.GT.0) Y(J,J)=Y(J,J)+YKK IF(I.GT.0.AND.J.GT.0) THEN Y(I,J)=Y(I,J)-YKK Y(J,I)=Y(J,I)-YKK ENDIF GOTO 4 ENDIF C add series RL element IF(TP(K).EQ.'RL'.OR.TP(K).EQ.'R') THEN YKK=0. RES=V1(K) IF(ABS(W).LE.0..AND.ABS(RES).LE.0.) RES=1.E-12 IF(ABS(RES).GT.0..OR.ABS(V2(K)).GT.0.) & YKK=1.D0/CMPLX(RES,W*V2(K)) IF(I.GT.0) Y(I,I)=Y(I,I)+YKK IF(J.GT.0) Y(J,J)=Y(J,J)+YKK IF(I.GT.0.AND.J.GT.0) THEN Y(I,J)=Y(I,J)-YKK Y(J,I)=Y(J,I)-YKK ENDIF GOTO 4 ENDIF C add transistor with current gain of HFE (assume 1 ohm base-emitter resistance) IF(TP(K).EQ.'TR') THEN IE=NF(K) IB=NT(K) IC=V1(K) HFE=V2(K) IF(IB.GT.0) Y(IB,IB)=Y(IB,IB)+1. IF(IE.GT.0) Y(IE,IE)=Y(IE,IE)+1. IF(IB.GT.0.AND.IE.GT.0) THEN Y(IB,IE)=Y(IB,IE)-1. Y(IE,IB)=Y(IE,IB)-1. ENDIF IF(IE.GT.0.) Y(IE,IE)=Y(IE,IE)+HFE IF(IE.GT.0.AND.IB.GT.0) Y(IE,IB)=Y(IE,IB)-HFE IF(IC.GT.0.AND.IB.GT.0) Y(IC,IB)=Y(IC,IB)+HFE IF(IC.GT.0.AND.IE.GT.0) Y(IC,IE)=Y(IC,IE)-HFE GOTO 4 ENDIF C add FET or tube with transconductance G = output drain current / input gate voltage IF(TP(K).EQ.'TU'.OR.TP(K).EQ.'FE') THEN ISOUR=NF(K) IGATE=NT(K) IDRAN=V1(K) G=V2(K) IF(ISOUR.GT.0.) Y(ISOUR,ISOUR)=Y(ISOUR,ISOUR)+G IF(ISOUR.GT.0.AND.IGATE.GT.0) Y(ISOUR,IGATE)=Y(ISOUR,IGATE)-G IF(IDRAN.GT.0.AND.IGATE.GT.0) Y(IDRAN,IGATE)=Y(IDRAN,IGATE)+G IF(IDRAN.GT.0.AND.ISOUR.GT.0) Y(IDRAN,ISOUR)=Y(IDRAN,ISOUR)-G GOTO 4 ENDIF C add ideal OP-amp with voltage gain AV = output voltage / input voltage IF(TP(K).EQ.'OA') THEN IPOS=NF(K) INEG=NT(K) IOUT=V1(K) AV=V2(K) IF(IOUT.LE.0) GOTO 4 IF(IPOS.GT.0) Y(IOUT,IPOS)=Y(IOUT,IPOS)-AV*1.E12 IF(INEG.GT.0) Y(IOUT,INEG)=Y(IOUT,INEG)+AV*1.E12 Y(IOUT,IOUT)=Y(IOUT,IOUT)+1.E12 GOTO 4 ENDIF C add two winding transformer model - second winding uses K+1 data IF(TP(K).EQ.'TF') THEN ERR='2nd TF RECORD IS MISSING' IF(K+1.GT.NE) GOTO 98 IF(TP(K+1).NE.'TF') GOTO 98 I1=NF(K) J1=NT(K) I2=NF(K+1) J2=NT(K+1) XL1=V1(K) XL2=V1(K+1) IF(V2(K+1).GT..999) V2(K+1)=.999 XLM=V2(K+1)*(XL1*XL2)**.5 XLC=XLM/(XLM*XLM-XL1*XL2) XLA=XLC*XL2/XLM XLB=XLC*XL1/XLM IF(ABS(W).GT.0.) THEN W1=-1./W W2=W1 ELSE W1=-1.E6 W2=0. ENDIF IF(I1.GT.0 ) Y(I1,I1)=Y(I1,I1)-CMPLX(0.,W1*XLA) IF(I1.GT.0.AND.J1.GT.0) Y(I1,J1)=Y(I1,J1)+CMPLX(0.,W1*XLA) IF(I1.GT.0.AND.I2.GT.0) Y(I1,I2)=Y(I1,I2)+CMPLX(0.,W2*XLC) IF(I1.GT.0.AND.J2.GT.0) Y(I1,J2)=Y(I1,J2)-CMPLX(0.,W2*XLC) IF(J1.GT.0.AND.I1.GT.0) Y(J1,I1)=Y(J1,I1)+CMPLX(0.,W1*XLA) IF(J1.GT.0 ) Y(J1,J1)=Y(J1,J1)-CMPLX(0.,W1*XLA) IF(J1.GT.0.AND.I2.GT.0) Y(J1,I2)=Y(J1,I2)-CMPLX(0.,W2*XLC) IF(J1.GT.0.AND.J2.GT.0) Y(J1,J2)=Y(J1,J2)+CMPLX(0.,W2*XLC) IF(I2.GT.0.AND.I1.GT.0) Y(I2,I1)=Y(I2,I1)+CMPLX(0.,W2*XLC) IF(I2.GT.0.AND.J1.GT.0) Y(I2,J1)=Y(I2,J1)-CMPLX(0.,W2*XLC) IF(I2.GT.0 ) Y(I2,I2)=Y(I2,I2)-CMPLX(0.,W1*XLB) IF(I2.GT.0.AND.J2.GT.0) Y(I2,J2)=Y(I2,J2)+CMPLX(0.,W1*XLB) IF(J2.GT.0.AND.I1.GT.0) Y(J2,I1)=Y(J2,I1)-CMPLX(0.,W2*XLC) IF(J2.GT.0.AND.J1.GT.0) Y(J2,J1)=Y(J2,J1)+CMPLX(0.,W2*XLC) IF(J2.GT.0.AND.I2.GT.0) Y(J2,I2)=Y(J2,I2)+CMPLX(0.,W1*XLB) IF(J2.GT.0 ) Y(J2,J2)=Y(J2,J2)-CMPLX(0.,W1*XLB) K=K+1 GOTO 4 ENDIF ERR='UNRECOGNIZABLE TYPE OF ELEMENT' GOTO 98 C------------------------------------------------------------------------------- C GAUSS ELIMINIATION MATRIX SOLUTION C------------------------------------------------------------------------------- ERR='SINGULAR MATRIX' 5 DO 9 K=1,NN IF(ABS(REAL(Y(K,K))).LE.0.AND.ABS(AIMAG(Y(K,K))).LE.0.) GOTO 98 YKK=1.D0/Y(K,K) DO 7 J=K,NA 7 Y(K,J)=Y(K,J)*YKK DO 9 I=1,NN IF(I.EQ.K) GOTO 9 YIK=Y(I,K) DO 8 J=1,NA 8 Y(I,J)=Y(I,J)-Y(K,J)*YIK 9 CONTINUE C------------------------------------------------------------------------------- C END OF MATRIX SOLUTION AND BEGINNING OF DATA PRINTOUT C------------------------------------------------------------------------------- C print out tabular data IF(AX.NE.'TA') GOTO 15 WRITE(6,'(40X,10HFREQUENCY=,1PE15.7,7H HERTZ)') F WRITE(6,'(40X,32H--------------------------------)') WRITE(6,10) 10 FORMAT(7X,'NODE REL-GAIN-DB ABS-GAIN-DB REAL-VOLTAGE IM &AG-VOLTAGE ABS-VOLTAGE PHASE') WRITE(6,11) 11 FORMAT(7X,'---- ----------- ----------- ------------ -- &---------- ----------- -----') DO 12 I=1,NN YD=20.*ALOG(CABS(Y(I,NA))/CABS(Y(1,NA)))/ALOG(10.) YB=CABS(Y(I,NA)) YC=20.*ALOG(YB)/ALOG(10.) ANG=ATAN2(AIMAG(Y(I,NA)),REAL(Y(I,NA)))*180./PI 12 WRITE(6,13) I,YC,YD,Y(I,NA),YB,ANG 13 FORMAT(I10,2F14.6,1P3E17.7,0PF13.6) WRITE(6,'(/)') GOTO 30 C print out graphic data 15 ERR='ILLEGAL NODE NUMBER TO GRAPH' IF(NG.LT.1.OR.NG.GT.NN) GOTO 98 ERR='Y AXIS SCALE ERROR' IF(YM.LE.0.) GOTO 98 YZ=CABS(Y(NG,NA)) YD=20.*ALOG(YZ)/ALOG(10.) ANG=ATAN2(AIMAG(Y(NG,NA)),REAL(Y(NG,NA)))*180./PI YCX=' ' IF(AX.EQ.'LO'.OR.AX.EQ.'LI') THEN YCX(11:11)='.' IF(N/10*10.EQ.N) YCX=YBX IY=(YZ*90./YM)+11.5 YD=YZ IF(IY.GE.1.AND.IY.LE.101) YCX(IY:IY)='*' ENDIF IF(AX.EQ.'BO') THEN YCX(51:51)='.' IF(N/10*10.EQ.N) YCX=YBX IY=(YD*50./YM)+51.5 IF(IY.GE.1.AND.IY.LE.101) YCX(IY:IY)='*' ENDIF WRITE(6,16) N,YCX,F,YD,ANG 16 FORMAT(I4,A101,1PE13.6,0PF7.1,F7.1) 30 CONTINUE IF(AX.EQ.'BO'.OR.AX.EQ.'LO'.OR.AX.EQ.'LI')WRITE(6,'(4X,A101)') YAX CLOSE(5) CLOSE(6) GOTO 99 97 WRITE(*,*) ERR STOP 98 WRITE(6,'(A32)') ERR CLOSE(6) 99 I=SYSTEM('NOTEPAD.EXE OP') STOP END