home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / tech / eepub05 / ciranl.pas < prev    next >
Pascal/Delphi Source File  |  1984-12-10  |  13KB  |  384 lines

  1. program CirAnl; { Performs Nodal Circuit Analysis for Freq Resp }
  2.  
  3. {             Jeff Crawford         December 10, 1984              }
  4. {                                                                  }
  5. {                          Version  1.0                            }
  6. {                                                                  }
  7. {                           REFERENCES                             }
  8. {                                                                  }
  9. {   [1]  "Unify Two-Port Calculations", D. J. Daruvala, Electronic }
  10. {        Design, January 4, & January 18, 1974 - Two Articles      }
  11. {   [2]  "High-Frequency Amplifiers, 2nd Edition", Ralph S. Carson,}
  12. {        John Wiley & Sons, 1982                                   }
  13.  
  14.  
  15. type     matrix    = array[1..25,1..25] of real;
  16.          vector    = array[1..100] of real;
  17.          XYData    = record
  18.                        XX,YY: real;
  19.                      end;
  20.          stat      = string[1];
  21.  
  22.  
  23. var      L,Cap         : matrix; { Inductance, Capacitance Terms Sqmodel }
  24.          Fyi,Fyr       : matrix; { Admittance Matrices; Real, Imag       }
  25.          F,F_low,F_high: real;   { Frequency Information                 }
  26.          F_inc         : real;   { Increment of Frequency                }
  27.          Nodes         : integer;{ Number of Nodes in Circuit; Passed from}
  28.                                  { Sqmodel Main Program                  }
  29.          omega         : real;   { Radian Frequency                      }
  30.          N             : integer;{ Parameter in Node Reduction Routine   }
  31.                                  { N Starts at Nodes and is Reduced by 1 }
  32.                                  { Until Arriving at N=2 for a Two-Port  }
  33.          No_turns      : integer;{ # Turns in Inductor - Passed from Main}
  34.          A,B           : matrix; { Equiv of Fyr,Fyi Matrices; Used in    }
  35.                                  { Matrix Reduction Routine to a 2 x 2   }
  36.          i,j           : integer;{ Used in Looping                       }
  37.          Freq,Mag      : vector; { Arrays to Hold Information of Z v.s. F}
  38.          Ans,Ans1,Ans2 : stat;   { Controls Function Routing          }
  39.          Num           : integer; { Number of Data Points Store on Disk  }
  40.  
  41.  
  42. Procedure Write_File( X,Y: vector);
  43.  
  44. var      j              : integer;
  45.          write_file     : file of XYData;
  46.          read_file      : file of XYData;
  47.          file_rec       : XYData;
  48.          file_name      : string[10];
  49.          file_size      : integer;
  50.          OK             : Boolean;
  51.          Ans1,Ans2      : string[1]; { Controls Program Routing      }
  52.  
  53. label 1,2;
  54.  
  55. begin
  56. 2:   clrscr;
  57.      gotoXY(10,10);
  58.      write('Write Data to What File  ? ');
  59.      readln(file_name);
  60.      assign(write_file,file_name);
  61.      {$I-} Reset(write_file) {$I+};
  62.      OK:= (IOresult = 0);     { Determines if File Already Exists }
  63.      if OK then
  64.          begin
  65.          clrscr;
  66.          gotoXY(10,10);
  67.          write('File Already Exists . . . Overwrite ?  Y / N ');
  68.          readln(Ans2);
  69.          Ans2:= upcase(Ans2);
  70.          if Ans2 <> 'Y' then goto 1;
  71.          end;
  72.     assign(write_file,file_name);
  73.     rewrite(write_file);
  74.     with file_rec do
  75.          begin
  76.          for j:= 1 to Num do   { Writes Data to Disk File }
  77.               begin
  78.               XX:= X[j];
  79.               YY:= X[j];
  80.               write(write_file,file_rec);
  81.               end;
  82.          end;
  83.     flush(write_file);
  84.     close(write_file);
  85. 1:  if Ans2 = 'N' then
  86.          begin
  87.          clrscr;
  88.          gotoXY(10,10);
  89.          write('Write Data to Different File   Y / N ?  ');
  90.          readln(Ans1);
  91.          Ans1:= upcase(Ans1);
  92.          if Ans1 = 'Y' then goto 2;
  93.          end;
  94. end;
  95.  
  96.  
  97. Procedure Swap(var X1,Y1: real); { Used to Swap Rows & Columns to   }
  98.                              { Change Input and/or Output Terminals }
  99.                              { for Calculation; Declared "var" so   }
  100.                              { Switch is Made in Major Matrices     }
  101.  
  102.     var   XX: real;
  103.  
  104.     begin
  105.          XX:= X1;
  106.          X1:= Y1;
  107.          Y1:= XX;
  108.     end;
  109.  
  110.  
  111.  
  112. Procedure Save_C(V: real; i,j: integer);  { Saves Capacitors }
  113.  
  114.     var  temp: real;
  115.  
  116.     begin
  117.          temp:= omega*V;
  118.          Fyi[i,i]:= Fyi[i,i] + temp;
  119.          Fyi[j,j]:= Fyi[j,j] + temp;
  120.          Fyi[i,j]:= Fyi[i,j] - temp;
  121.          Fyi[j,i]:= Fyi[j,i] - temp;
  122.     end;
  123.  
  124. Procedure Save_L(V: real; i,j: integer);
  125.  
  126.     var  temp: real;
  127.  
  128.     begin
  129.          temp:= -1.0/(omega*V);
  130.          Fyi[i,i]:= Fyi[i,i] + temp;
  131.          Fyi[j,j]:= Fyi[j,j] + temp;
  132.          Fyi[i,j]:= Fyi[i,j] - temp;
  133.          Fyi[j,i]:= Fyi[j,i] - temp;
  134.     end;
  135.  
  136.  
  137.  
  138. Procedure Fill_Caps(var N: integer);
  139.     var  i : integer;
  140.  
  141.     begin
  142.          for i:= 2 to N-1 do
  143.               begin
  144.                    Save_C(cap[i-1,i-1],i,0);
  145.               end;
  146.          for i:= 2 to N-2 do
  147.               begin
  148.                    Save_C(cap[i-1,i], i, i+1);
  149.               end;
  150.     end;
  151.  
  152.  
  153. Procedure Fill_Inductors(var N: integer);
  154.  
  155.     var  i              : integer;
  156.          Ind_val        : real;
  157.  
  158.     begin
  159.          Save_L(0.5*L[1,1],1,2);
  160.          Save_L(0.5*L[N-2,N-2], N-1,N);
  161.          for i:= 2 to N-2 do
  162.               begin
  163.                    Ind_val:= 1/(0.5*(L[i-1,i-1] + L[i,i])) + 1.0/L[i-1,i];
  164.                                 { i,j are Coupled Turn Designators }
  165.                    Save_L(1.0/Ind_val,i,i+1);
  166.               end;
  167.          for i:= 2 to N-1 do
  168.               begin
  169.                    for j:= i+2 to N-1 do
  170.                         begin
  171.                              Save_L(L[i-1,j-1], i,j);
  172.                         end;
  173.                end;
  174.     end;
  175.  
  176.  
  177. Procedure Reduce_Mat(In_node,Out_node:integer; N:integer; var A,B:matrix);
  178.  
  179. { Reduces Beginning N*N Floating Admittance Matrix to an Equivalent Two - }
  180. { Port Representation by Proper Matrix Reduction Techniques Discussed in  }
  181. { the References Sited.  After the Necessary Swapping to Place Input Node }
  182. { in Columns/Row 1 and Output Node in 2, Reference Node in 3, The Starting}
  183. { Matrix is Reduced Down to a Two-Port Representation.                    }
  184.  
  185. var      Den      : real; { Magnitude of Yrr                              }
  186.          r        : integer; { Row & Column Being Reduced                 }
  187.          i,j      : integer;
  188.          LL       : integer; { Largest Diagonal Element Row - Better      }
  189.          XX1      : real; { Real Part of Common Term Subtracted From      }
  190.                           { Yps in Reduction Process                      }
  191.          YY1      : real; { Imag Part of Common Term Subtracted From      }
  192.                           { Yps in Reduction Process                      }
  193.          S1,S     : real; { Tests for Largest Diagonal Element; Done to   }
  194.                           { Retain as Much Accuracy as Possible in the    }
  195.                           { Reduction Process                             }
  196.  
  197.  
  198.     begin
  199.          if (In_node <> 1) or (Out_node <> 2) then   { Swap In & Out }
  200.          begin
  201.               for j:= 1 to N do
  202.                    begin
  203.                    Swap(A[1,j], A[In_node,j]);
  204.                    Swap(B[1,j], B[In_node,j]);
  205.                    Swap(A[2,j], A[Out_node,j]);
  206.                    Swap(B[2,j], B[Out_node,j]);
  207.                    end;
  208.               for i:= 1 to N do
  209.                    begin
  210.                    Swap(A[i,1], A[i,In_node]);
  211.                    Swap(B[i,1], B[i,In_node]);
  212.                    Swap(A[i,2], A[i,Out_node]);
  213.                    Swap(B[i,2], B[i,Out_node]);
  214.                    end;
  215.          end;
  216.     while N > 2 do { Finds Largest Diagonal Element in Rows Remaining     }
  217.                    { to be Reduced to Enhance Accuracy and Performs the   }
  218.                    { Necessary Swapping                                   }
  219.          begin
  220.          LL:= 3;
  221.          S:= abs( A[LL,LL] ) + abs( B[LL,LL] );
  222.          if N > 3 then
  223.               begin
  224.               for i:= 4 to N do
  225.                    begin
  226.                    S1:= abs( A[i,i] ) + abs( B[i,i] );
  227.                    if S1 > S then
  228.                         begin
  229.                         S:= S1;
  230.                         LL:= i;
  231.                         end;
  232.                    end;
  233.               end;
  234.          if LL <> N then
  235.               begin
  236.               for j:= 1 to N do
  237.                    begin
  238.                    Swap( A[LL,j],A[N,j]);
  239.                    Swap( B[LL,j],B[N,j]);
  240.                    end;
  241.               for i:= 1 to N do
  242.                    begin
  243.                    Swap( A[i,LL], A[i,N]);
  244.                    Swap( B[i,LL],B[i,N]);
  245.                    end;
  246.               end;
  247.          Den:= sqr(A[N,N]) + sqr(B[N,N]); { Beginning of Main Reduction }
  248.          r:= N;
  249.          N:= N - 1;
  250.          for i:= 1 to N do
  251.               begin
  252.               if (A[i,r] <> 0) or (B[i,r] <> 0) then
  253.                    begin
  254.                    XX1:= (A[i,r]*A[r,r] + B[r,r]*B[i,r])/Den;
  255.                    YY1:= (A[r,r]*B[i,r] - A[i,r]*B[r,r])/Den;
  256.                    for j:= 1 to N do
  257.                         begin
  258.                         if (A[r,j]<> 0) or (B[r,j]<> 0) then
  259.                              begin
  260.                              A[i,j]:= A[i,j] - A[r,j]*XX1 + B[r,j]*YY1;
  261.                              B[i,j]:= B[i,j] - A[r,j]*YY1 - B[r,j]*XX1;
  262.                              end;
  263.                         end;
  264.                    end;
  265.               end;
  266.          end;
  267. end;
  268.  
  269. Procedure Out_put(Ans2: stat; var FYr,FYi:matrix );
  270.  
  271. begin
  272.     write('  ',F:6:3,'  ',Fyr[1,1]:6:4,'  ',Fyi[1,1]:6:4,'  ',Fyr[1,2]:6:4);
  273.     write('  ',Fyi[1,2]:6:4,'  ',Fyr[2,1]:6:4,'  ',Fyi[2,1]:6:4);
  274.     writeln('  ',Fyr[2,2]:6:4,'  ',Fyi[2,2]:6:4);
  275.     if Ans2 = 'Y' then
  276.     begin
  277.     write(LST,'  ',F:6:3,'  ',Fyr[1,1]:6:4,'  ',Fyi[1,1]:6:4,'  ',Fyr[1,2]:6:4);
  278.     write(LST,'  ',Fyi[1,2]:6:4,'  ',Fyr[2,1]:6:4,'  ',Fyi[2,1]:6:4);
  279.     writeln(LST,'  ',Fyr[2,2]:6:4,'  ',Fyi[2,2]:6:4);
  280.     end;
  281. end;
  282.  
  283.  
  284. { //////////////////////////////////////////////////////////////////// }
  285. { //////////////////////         MAIN              /////////////////// }
  286. { //////////////////////        BLOCK              /////////////////// }
  287. { //////////////////////////////////////////////////////////////////// }
  288.  
  289. begin
  290. No_turns:= 4;
  291. L[1,2]:= 3.08175E-11;
  292. L[1,3]:= 2.54812E-11;
  293. L[1,4]:= 2.27640E-11;
  294. L[2,3]:= 4.78563E-11;
  295. L[2,4]:= 3.85507E-11;
  296. L[3,4]:= 6.57417E-11;
  297. L[1,1]:= 7.7183E-11;
  298. L[2,2]:= 1.2684E-10;
  299. L[3,3]:= 1.8074E-10;
  300. L[4,4]:= 2.378E-10;
  301. cap[1,2]:= 6.21531E-15;
  302. cap[2,3]:= 8.56065E-15;
  303. cap[3,4]:= 1.0906E-14;
  304. cap[2,0]:= 1.41149E-15;
  305. cap[3,0]:= 1.85961E-15;
  306. cap[1,1]:= 4.02368E-15;
  307. cap[4,4]:= 9.6381E-15;
  308. for i:= 1 to 25 do
  309.     begin
  310.     for j:= 1 to 25 do
  311.          begin
  312.          Fyr[i,j]:= 0.0;
  313.          Fyi[i,j]:= 0.0;
  314.          A[i,j]:= 0.0;
  315.          B[i,j]:= 0.0;
  316.          end;
  317.     end;
  318. Ans2:= 'N';
  319. clrscr;
  320. gotoXY(10,10);
  321. write('Enter Lower, Upper, & Freq-Increment,  GHz  ');
  322. readln(F_low, F_high, F_inc);
  323. F:= F_low;
  324. writeln;
  325. write('         Is a Hard-Copy Desired  Y / N ');
  326. readln(Ans2);
  327. Ans2:= upcase(Ans2);
  328. Nodes:= No_turns + 2;
  329. Num:= 0;
  330. clrscr;
  331. gotoXY(1,2);
  332. write('                         Two - Port Admittance Parameters ');
  333. writeln;
  334. write('  Freq           Y11             Y12    ');
  335. writeln('         Y21             Y22');
  336. write('  GHz        Real    Imag     Real Imag  ');
  337. writeln('    Real  Imag      Real  Imag');
  338. writeln;
  339. if Ans2 = 'Y' then
  340.     begin
  341.     writeln(LST,'                   Two - Port Admittance Parameters ');
  342.     writeln(LST);
  343.     write(LST,'  Freq           Y11              Y12    ');
  344.     writeln(LST,'         Y21             Y22');
  345.     write(LST,'  GHz        Real    Imag      Real Imag  ');
  346.     writeln(LST,'    Real  Imag      Real  Imag');
  347.     writeln(LST);
  348.     end;
  349. while F<= F_high do
  350.     begin
  351.     Num:= Num + 1;
  352.     Omega:= F*2*Pi*1.0E9;
  353.     N:= Nodes;
  354.     for i:= 1 to N do
  355.          begin
  356.          for j:= 1 to N do
  357.               begin
  358.               Fyr[i,j]:= 0.0;
  359.               Fyi[i,j]:= 0.0;
  360.               end;
  361.          end;
  362.     Fill_Caps(N);
  363.     Fill_inductors(N);
  364.     Reduce_Mat(1,Nodes,N,Fyr,Fyi);
  365.     Freq[Num]:= F;
  366.     Mag[Num]:= -1.0/Fyi[1,1];
  367.     Out_put(Ans2,Fyr,Fyi);
  368.     F:= F + F_inc;
  369.     end;
  370.     write('                                              ');
  371.     writeln('          Any Key to Continue ');
  372.     repeat
  373.         delay(100);
  374.     until keypressed;
  375.     clrscr;
  376.     gotoXY(10,10);
  377.     write('Store Data to Disk ?  Y/N ');
  378.     readln(Ans);
  379.     Ans:= upcase(Ans);
  380.     if Ans = 'Y' then Write_file(Freq,Mag);
  381. end.
  382.  
  383.  
  384.