148082Sbostic(* 2*62158Sbostic * Copyright (c) 1980, 1993 3*62158Sbostic * The Regents of the University of California. All rights reserved. 448082Sbostic * 548082Sbostic * %sccs.include.redist.c% 648082Sbostic * 7*62158Sbostic * @(#)parall.p 8.1 (Berkeley) 06/06/93 848082Sbostic *) 948082Sbostic 1048082Sbosticprogram Parall(input,output); 1148082Sbostic 1248082Sbostic{Declare constants for unit conversions, convergence tests, etc.} 1348082Sbostic 1448082Sbosticconst SQRT2 = 1.4142136; {Square root of 2} 1548082Sbostic TWOPI = 6.2831853; {Two times pi} 1648082Sbostic MINALPHA = 0.001; {Minimum y-step size} 1748082Sbostic ROUGHLYZERO = 0.001; {Approximation to zero for convergence} 1848082Sbostic YTHRESHOLD = 40.0; {Heuristic constant for thresholding} 1948082Sbostic N = 8; {Vector and matrix dimension} 2048082Sbostic 2148082Sbostic 2248082Sbostic{Declare types for circuit elements, vectors, and matrices.} 2348082Sbostic 2448082Sbostictype VSOURCE = record 2548082Sbostic ampl: real; {Volts (peak)} 2648082Sbostic freq: real; {Radians/second} 2748082Sbostic xindex: integer; {Index for x value} 2848082Sbostic yindex: integer; {Index for y value} 2948082Sbostic end; 3048082Sbostic 3148082Sbostic RLPAIR = record 3248082Sbostic r: real; {Ohms} 3348082Sbostic l: real; {Henries} 3448082Sbostic islope: real; {Amps/second} 3548082Sbostic invariant: real; {Trapezoidal invariant} 3648082Sbostic lasttime: real; {Most recent time} 3748082Sbostic xindex: array [1..2] of integer; {x value indices} 3848082Sbostic yindex: array [1..2] of integer; {y value indices} 3948082Sbostic end; 4048082Sbostic 4148082Sbostic CAPACITOR = record 4248082Sbostic c: real; {Farads} 4348082Sbostic vslope: real; {Volts/second} 4448082Sbostic invariant: real; {Trapezoidal invariant} 4548082Sbostic lasttime: real; {Most recent time} 4648082Sbostic xindex: array [1..2] of integer; {x value indices} 4748082Sbostic yindex: array [1..2] of integer; {y value indices} 4848082Sbostic end; 4948082Sbostic 5048082Sbostic VECTOR = array [1..N] of real; 5148082Sbostic 5248082Sbostic MATRIX = array [1..N,1..N] of real; 5348082Sbostic 5448082Sbostic 5548082Sbostic{Declare global variables for central simulation information.} 5648082Sbostic 5748082Sbosticvar ground: VSOURCE; {Ground -- a fake source} 5848082Sbostic itcount: integer; {Main routine iteration count} 5948082Sbostic update: integer; {Update loop counter for main} 6048082Sbostic optimcount: integer; {Number of optimization steps} 6148082Sbostic newtoncount: integer; {Number of Newton steps} 6248082Sbostic v1: VSOURCE; {Voltage source V1} 6348082Sbostic rl1: RLPAIR; {R1/L1 resistor-inductor pair} 6448082Sbostic rl2: RLPAIR; {R2/L2 resistor-inductor pair} 6548082Sbostic c1: CAPACITOR; {Capacitor C1} 6648082Sbostic a: MATRIX; {Global matrix A} 6748082Sbostic b: MATRIX; {Global matrix B} 6848082Sbostic jac: MATRIX; {Global Jacobian matrix} 6948082Sbostic x: VECTOR; {Global vector of dependents} 7048082Sbostic xnext: VECTOR; {Next x-vector for simulation} 7148082Sbostic y: VECTOR; {Global vector of independents} 7248082Sbostic ynext: VECTOR; {Next y-vector for simulation} 7348082Sbostic gradient: VECTOR; {Global gradient vector} 7448082Sbostic h: real; {Time step value} 7548082Sbostic time: real; {Current time} 7648082Sbostic lastychange: real; {YStep's most recent y-change} 7748082Sbostic timestep: integer; {Current timestep number} 7848082Sbostic maxsteps: integer; {Number of time steps to run} 7948082Sbostic oldxnorm: real; {Old one-norm of x-vector} 8048082Sbostic newxnorm: real; {New one-norm of x-vector} 8148082Sbostic closenough: boolean; {Flag to indicate convergence} 8248082Sbostic 8348082Sbostic 8448082Sbostic 8548082Sbostic 8648082Sbostic{The following procedure initializes everything for the program based 8748082Sbostic on the little test circuit suggested by Sarosh. The user is asked 8848082Sbostic to specify the simulation and circuit parameters, and then the matrix 8948082Sbostic and vector values are set up.} 9048082Sbostic 9148082Sbosticprocedure InitializeEverything; 9248082Sbosticvar i,j: integer; 9348082Sbostic rtemp: real; 9448082Sbosticbegin 9548082Sbostic 9648082Sbostic{Ready the input and output files (almost nil for Berkeley).} 9748082Sbosticwriteln(output); 9848082Sbosticwriteln(output,'*** Simulation Output Record ***'); 9948082Sbosticwriteln(output); 10048082Sbosticwriteln(output); 10148082Sbostic 10248082Sbostic{Initialize convergence test/indication variables.} 10348082Sbosticoldxnorm := 0.0; 10448082Sbosticnewxnorm := 0.0; 10548082Sbosticlastychange := 0.0; 10648082Sbostic 10748082Sbostic{Get desired time step size for simulation.} 10848082Sbosticreadln(input,h); 10948082Sbosticwriteln(output,'h (Seconds): ',h:12:7); 11048082Sbostic 11148082Sbostic{Get desired number of time steps for simulation.} 11248082Sbosticreadln(input,maxsteps); 11348082Sbosticwriteln(output,'maxsteps: ',maxsteps:4); 11448082Sbostic 11548082Sbostic{Get parameters for source V1 and initialize the source.} 11648082Sbosticwith v1 do 11748082Sbostic begin 11848082Sbostic readln(input,rtemp); 11948082Sbostic writeln(output,'V1 (Volts RMS): ',rtemp:9:3); 12048082Sbostic ampl := rtemp * SQRT2; 12148082Sbostic readln(input,rtemp); 12248082Sbostic writeln(output,'f (Hertz): ',rtemp:9:3); 12348082Sbostic freq := rtemp * TWOPI; 12448082Sbostic xindex := 1; 12548082Sbostic yindex := 1; 12648082Sbostic end; 12748082Sbostic 12848082Sbostic{Get parameters for R1/L1 pair and initialize the pair.} 12948082Sbosticwith rl1 do 13048082Sbostic begin 13148082Sbostic readln(input,r); 13248082Sbostic writeln(output,'R1 (Ohms): ',r:9:3); 13348082Sbostic readln(input,l); 13448082Sbostic writeln(output,'L1 (Henries): ',l:12:7); 13548082Sbostic islope := 0.0; 13648082Sbostic invariant := 0.0; 13748082Sbostic lasttime := -1.0; {Negative to force first update} 13848082Sbostic xindex[1] := 2; 13948082Sbostic yindex[1] := 2; 14048082Sbostic xindex[2] := 3; 14148082Sbostic yindex[2] := 3; 14248082Sbostic end; 14348082Sbostic 14448082Sbostic{Get parameters for R2/L2 pair and initialize the pair.} 14548082Sbosticwith rl2 do 14648082Sbostic begin 14748082Sbostic readln(input,r); 14848082Sbostic writeln(output,'R2 (Ohms): ',r:9:3); 14948082Sbostic readln(input,l); 15048082Sbostic writeln(output,'L2 (Henries): ',l:12:7); 15148082Sbostic islope := 0.0; 15248082Sbostic invariant := 0.0; 15348082Sbostic lasttime := -1.0; {Negative to force first update} 15448082Sbostic xindex[1] := 4; 15548082Sbostic yindex[1] := 4; 15648082Sbostic xindex[2] := 5; 15748082Sbostic yindex[2] := 5; 15848082Sbostic end; 15948082Sbostic 16048082Sbostic{Get parameters for capacitor C1 and initialize the device.} 16148082Sbosticwith c1 do 16248082Sbostic begin 16348082Sbostic readln(input,c); 16448082Sbostic writeln(output,'C1 (Farads): ',c:12:7); 16548082Sbostic vslope := 0.0; 16648082Sbostic invariant := 0.0; 16748082Sbostic lasttime := -1.0; {Negative to force first update} 16848082Sbostic xindex[1] := 6; 16948082Sbostic yindex[1] := 6; 17048082Sbostic xindex[2] := 7; 17148082Sbostic yindex[2] := 7; 17248082Sbostic end; 17348082Sbostic 17448082Sbostic{Initialize the ground node.} 17548082Sbosticwith ground do 17648082Sbostic begin 17748082Sbostic ampl := 0.0; 17848082Sbostic freq := 0.0; 17948082Sbostic xindex := 8; 18048082Sbostic yindex := 8; 18148082Sbostic end; 18248082Sbostic 18348082Sbostic{Zero out all the vectors and matrices.} 18448082Sbosticfor i := 1 to N do 18548082Sbostic begin 18648082Sbostic x[i] := 0.0; 18748082Sbostic y[i] := 0.0; 18848082Sbostic for j := 1 to N do 18948082Sbostic begin 19048082Sbostic a[i,j] := 0.0; 19148082Sbostic b[i,j] := 0.0; 19248082Sbostic jac[i,j] := 0.0; 19348082Sbostic end; 19448082Sbostic end; 19548082Sbostic 19648082Sbostic{Initialize the A matrix.} 19748082Sbostica[1,2] := -1.0; 19848082Sbostica[2,3] := 1.0; 19948082Sbostica[2,4] := -1.0; 20048082Sbostica[3,5] := 1.0; 20148082Sbostica[4,7] := 1.0; 20248082Sbostica[5,1] := 1.0; 20348082Sbostica[7,6] := 1.0; 20448082Sbostica[8,8] := 1.0; 20548082Sbostic 20648082Sbostic{Initialize the B matrix.} 20748082Sbosticb[1,1] := 1.0; 20848082Sbosticb[3,7] := -1.0; 20948082Sbosticb[4,8] := -1.0; 21048082Sbosticb[5,2] := 1.0; 21148082Sbosticb[6,3] := 1.0; 21248082Sbosticb[6,4] := 1.0; 21348082Sbosticb[7,5] := 1.0; 21448082Sbosticb[8,6] := 1.0; 21548082Sbostic 21648082Sbostic{Initialize the Jacobian matrix.} 21748082Sbosticrtemp := h / (2.0 * rl1.l + rl1.r * h); 21848082Sbosticjac[2,2] := rtemp; 21948082Sbosticjac[3,3] := rtemp; 22048082Sbosticjac[2,3] := -rtemp; 22148082Sbosticjac[3,2] := -rtemp; 22248082Sbosticrtemp := h / (2.0 * rl2.l + rl2.r * h); 22348082Sbosticjac[4,4] := rtemp; 22448082Sbosticjac[5,5] := rtemp; 22548082Sbosticjac[4,5] := -rtemp; 22648082Sbosticjac[5,4] := -rtemp; 22748082Sbosticjac[6,6] := -1.0; 22848082Sbosticjac[7,7] := 1.0; 22948082Sbosticjac[7,6] := h / (2.0 * c1.c); 23048082Sbosticend; 23148082Sbostic 23248082Sbostic 23348082Sbostic 23448082Sbostic 23548082Sbostic{The following procedure solves the equation Ax=b for an N x N system 23648082Sbostic of linear equations, where A is the coefficient matrix, b is the 23748082Sbostic right-hand-side vector, and x is the vector of unknowns. Gaussian 23848082Sbostic elimination with maximal column pivots is used. } 23948082Sbostic 24048082Sbosticprocedure Solve(a: MATRIX; b: VECTOR; var x: VECTOR); 24148082Sbosticvar y,z: real; 24248082Sbostic i,j,k,k1: integer; 24348082Sbosticbegin 24448082Sbosticfor k := 1 to N-1 do 24548082Sbostic begin 24648082Sbostic y := abs(a[k,k]); 24748082Sbostic j := k; 24848082Sbostic k1 := k + 1; 24948082Sbostic for i := k1 to N do 25048082Sbostic if abs(a[i,k]) > y then 25148082Sbostic begin 25248082Sbostic j := i; 25348082Sbostic y := abs(a[i,k]); 25448082Sbostic end; 25548082Sbostic for i := k to N do 25648082Sbostic begin 25748082Sbostic y := a[k,i]; 25848082Sbostic a[k,i] := a[j,i]; 25948082Sbostic a[j,i] := y; 26048082Sbostic end; 26148082Sbostic y := b[k]; 26248082Sbostic b[k] := b[j]; 26348082Sbostic b[j] := y; 26448082Sbostic z := a[k,k]; 26548082Sbostic for i := k1 to N do 26648082Sbostic begin 26748082Sbostic y := a[i,k] / z; 26848082Sbostic a[i,k] := y; 26948082Sbostic for j := k1 to N do a[i,j] := a[i,j] - y * a[k,j]; 27048082Sbostic b[i] := b[i] - y * b[k]; 27148082Sbostic end; 27248082Sbostic end; 27348082Sbosticx[N] := b[N] / a[N,N]; 27448082Sbosticfor i := N-1 downto 1 do 27548082Sbostic begin 27648082Sbostic y := b[i]; 27748082Sbostic for j := i+1 to N do y := y - a[i,j] * x[j]; 27848082Sbostic x[i] := y / a[i,i]; 27948082Sbostic end; 28048082Sbosticend; 28148082Sbostic 28248082Sbostic 28348082Sbostic{The following procedure computes and returns a vector called "deltay", 28448082Sbostic which is the change in the y-vector prescribed by the Newton-Rhapson 28548082Sbostic algorithm.} 28648082Sbostic 28748082Sbosticprocedure NewtonStep(var deltay: VECTOR); 28848082Sbosticvar phi: VECTOR; 28948082Sbostic m: MATRIX; 29048082Sbostic i,j,k: integer; 29148082Sbosticbegin 29248082Sbosticfor i := 1 to N do 29348082Sbostic begin 29448082Sbostic phi[i] := 0.0; 29548082Sbostic for j := 1 to N do 29648082Sbostic begin 29748082Sbostic phi[i] := phi[i] + a[i,j] * y[j] + b[i,j] * x[j]; 29848082Sbostic m[i,j] := -a[i,j]; 29948082Sbostic for k := 1 to N do m[i,j] := m[i,j] - b[i,k] * jac[k,j]; 30048082Sbostic end; 30148082Sbostic 30248082Sbostic end; 30348082SbosticSolve(m,phi,deltay); 30448082Sbosticend; 30548082Sbostic 30648082Sbostic 30748082Sbostic 30848082Sbostic 30948082Sbostic{The following function computes the value of theta, the objective 31048082Sbostic function, given the x and y vectors.} 31148082Sbostic 31248082Sbosticfunction ThetaValue(x,y: VECTOR): real; 31348082Sbosticvar i,j: integer; 31448082Sbostic phielem: real; 31548082Sbostic theta: real; 31648082Sbosticbegin 31748082Sbostictheta := 0.0; 31848082Sbosticfor i:= 1 to N do 31948082Sbostic begin 32048082Sbostic phielem := 0.0; 32148082Sbostic for j := 1 to N do 32248082Sbostic phielem := phielem + a[i,j] * y[j] + b[i,j] * x[j]; 32348082Sbostic theta := theta + phielem * phielem; 32448082Sbostic end; 32548082SbosticThetaValue := theta; 32648082Sbosticend; 32748082Sbostic 32848082Sbostic 32948082Sbostic{The following function computes the theta value associated with a 33048082Sbostic proposed step of size alpha in the direction of the gradient.} 33148082Sbostic 33248082Sbosticfunction Theta(alpha: real): real; 33348082Sbosticvar ythere: VECTOR; 33448082Sbostic i: integer; 33548082Sbosticbegin 33648082Sbosticfor i := 1 to N do 33748082Sbostic ythere[i] := y[i] - alpha * gradient[i]; 33848082SbosticTheta := ThetaValue(x,ythere); 33948082Sbosticend; 34048082Sbostic 34148082Sbostic 34248082Sbostic{The following procedure computes the gradient of the objective 34348082Sbostic function (theta) with respect to the vector y.} 34448082Sbostic 34548082Sbosticprocedure ComputeGradient; 34648082Sbosticvar i,j,k: integer; 34748082Sbostic m: MATRIX; 34848082Sbostic v: VECTOR; 34948082Sbosticbegin 35048082Sbostic{Compute v = Ay + Bx and M = A' + J'B'.} 35148082Sbosticfor i := 1 to N do 35248082Sbostic begin 35348082Sbostic v[i] := 0.0; 35448082Sbostic for j := 1 to N do 35548082Sbostic begin 35648082Sbostic v[i] := v[i] + a[i,j] * y[j] + b[i,j] * x[j]; 35748082Sbostic m[i,j] := a[j,i]; 35848082Sbostic for k := 1 to N do 35948082Sbostic m[i,j] := m[i,j] + jac[k,i] * b[j,k]; 36048082Sbostic end; 36148082Sbostic end; 36248082Sbostic{Compute gradient = 2Mv.} 36348082Sbosticfor i := 1 to N do 36448082Sbostic begin 36548082Sbostic gradient[i] := 0.0; 36648082Sbostic for j := 1 to N do 36748082Sbostic gradient[i] := gradient[i] + m[i,j] * v[j]; 36848082Sbostic gradient[i] := 2.0 * gradient[i]; 36948082Sbostic end; 37048082Sbosticend; 37148082Sbostic 37248082Sbostic 37348082Sbostic{The following procedure computes the bounds on alpha, the step size 37448082Sbostic to take in the gradient direction. The bounding is done according 37548082Sbostic to an algorithm suggested in S.W.Director's text on circuits.} 37648082Sbostic 37748082Sbosticprocedure GetAlphaBounds(var lower,upper: real); 37848082Sbosticvar alpha: real; 37948082Sbostic oldtheta,newtheta: real; 38048082Sbosticbegin 38148082Sbosticif ThetaValue(x,y) = 0.0 38248082Sbostic then 38348082Sbostic begin 38448082Sbostic lower := 0; 38548082Sbostic 38648082Sbostic upper := 0; 38748082Sbostic end 38848082Sbostic else 38948082Sbostic begin 39048082Sbostic lower := MINALPHA; 39148082Sbostic oldtheta := Theta(lower); 39248082Sbostic upper := MINALPHA * 2.0; 39348082Sbostic newtheta := Theta(upper); 39448082Sbostic if newtheta <= oldtheta then 39548082Sbostic begin 39648082Sbostic alpha := upper; 39748082Sbostic repeat 39848082Sbostic begin 39948082Sbostic oldtheta := newtheta; 40048082Sbostic alpha := alpha * 2.0; 40148082Sbostic newtheta := Theta(alpha); 40248082Sbostic end 40348082Sbostic until (newtheta > oldtheta); 40448082Sbostic lower := alpha / 4.0; 40548082Sbostic upper := alpha; 40648082Sbostic end; 40748082Sbostic end; 40848082Sbosticend; 40948082Sbostic 41048082Sbostic 41148082Sbostic{The following function computes the best value of alpha for the step 41248082Sbostic in the gradient direction. This best value is the value that minimizes 41348082Sbostic theta along the gradient-directed path.} 41448082Sbostic 41548082Sbosticfunction BestAlpha(lower,upper: real): real; 41648082Sbosticvar alphaL,alphaU,alpha1,alpha2: real; 41748082Sbostic thetaL,thetaU,theta1,theta2: real; 41848082Sbostic 41948082Sbosticbegin 42048082SbosticalphaL := lower; 42148082SbosticthetaL := Theta(alphaL); 42248082SbosticalphaU := upper; 42348082SbosticthetaU := Theta(alphaU); 42448082Sbosticalpha1 := 0.381966 * alphaU + 0.618034 * alphaL; 42548082Sbostictheta1 := Theta(alpha1); 42648082Sbosticalpha2 := 0.618034 * alphaU + 0.381966 * alphaL; 42748082Sbostictheta2 := Theta(alpha2); 42848082Sbosticrepeat 42948082Sbostic if theta1 < theta2 43048082Sbostic then 43148082Sbostic begin 43248082Sbostic alphaU := alpha2; 43348082Sbostic thetaU := theta2; 43448082Sbostic alpha2 := alpha1; 43548082Sbostic theta2 := theta1; 43648082Sbostic alpha1 := 0.381966 * alphaU + 0.618034 * alphaL; 43748082Sbostic theta1 := Theta(alpha1); 43848082Sbostic end 43948082Sbostic else 44048082Sbostic begin 44148082Sbostic alphaL := alpha1; 44248082Sbostic thetaL := theta1; 44348082Sbostic alpha1 := alpha2; 44448082Sbostic theta1 := theta2; 44548082Sbostic alpha2 := 0.618034 * alphaU + 0.381966 * alphaL; 44648082Sbostic theta2 := Theta(alpha2); 44748082Sbostic end 44848082Sbosticuntil abs(thetaU - thetaL) <= ROUGHLYZERO; 44948082SbosticBestAlpha := (alphaL + alphaU) / 2.0; 45048082Sbosticend; 45148082Sbostic 45248082Sbostic 45348082Sbostic{The following procedure computes and returns a vector called "deltay", 45448082Sbostic which is the change in the y-vector prescribed by the steepest-descent 45548082Sbostic approach.} 45648082Sbostic 45748082Sbosticprocedure OptimizationStep(var deltay: VECTOR); 45848082Sbosticvar lower,upper: real; 45948082Sbostic alpha: real; 46048082Sbostic i: integer; 46148082Sbosticbegin 46248082SbosticComputeGradient; 46348082SbosticGetAlphaBounds(lower,upper); 46448082Sbosticif lower <> upper then 46548082Sbostic begin 46648082Sbostic alpha := BestAlpha(lower,upper); 46748082Sbostic for i:= 1 to N do deltay[i] := - alpha * gradient[i]; 46848082Sbostic end; 46948082Sbosticend; 47048082Sbostic 47148082Sbostic 47248082Sbostic 47348082Sbostic 47448082Sbostic{The following function computes the one-norm of a vector argument. 47548082Sbostic The length of the argument vector is assumed to be N.} 47648082Sbostic 47748082Sbosticfunction OneNorm(vec: VECTOR): real; 47848082Sbosticvar sum: real; 47948082Sbostic i: integer; 48048082Sbosticbegin 48148082Sbosticsum := 0; 48248082Sbosticfor i := 1 to N do sum := sum + abs(vec[i]); 48348082SbosticOneNorm := sum; 48448082Sbosticend; 48548082Sbostic 48648082Sbostic 48748082Sbostic{The following procedure takes a y-step, using the optimization 48848082Sbosticapproach when far from the solution and the Newton-Rhapson approach 48948082Sbosticwhen fairly close to the solution.} 49048082Sbostic 49148082Sbosticprocedure YStep; 49248082Sbosticvar deltay: VECTOR; 49348082Sbostic ychange: real; 49448082Sbostic scale: real; 49548082Sbostic i: integer; 49648082Sbosticbegin 49748082SbosticNewtonStep(deltay); 49848082Sbosticychange := OneNorm(deltay); 49948082Sbosticif ychange > YTHRESHOLD 50048082Sbostic then 50148082Sbostic{ 50248082Sbostic begin 50348082Sbostic OptimizationStep(deltay); 50448082Sbostic ychange := OneNorm(deltay); 50548082Sbostic if ychange > YTHRESHOLD then 50648082Sbostic} 50748082Sbostic begin 50848082Sbostic scale := YTHRESHOLD/ychange; 50948082Sbostic for i := 1 to N do deltay[i] := scale * deltay[i]; 51048082Sbostic optimcount := optimcount + 1; 51148082Sbostic end {;} 51248082Sbostic{ 51348082Sbostic optimcount := optimcount + 1; 51448082Sbostic end 51548082Sbostic} 51648082Sbostic else 51748082Sbostic begin 51848082Sbostic newtoncount := newtoncount + 1; 51948082Sbostic end; 52048082Sbosticfor i := 1 to N do ynext[i] := y[i] + deltay[i]; 52148082Sbosticend; 52248082Sbostic 52348082Sbostic 52448082Sbostic 52548082Sbostic 52648082Sbostic{The following procedure updates the output of a voltage source 52748082Sbostic given the current time.} 52848082Sbostic 52948082Sbosticprocedure VsourceStep(vn: VSOURCE); 53048082Sbosticbegin 53148082Sbosticwith vn do 53248082Sbostic xnext[xindex] := ampl * sin(freq * time); 53348082Sbosticend; 53448082Sbostic 53548082Sbostic 53648082Sbostic{The following procedure updates the outputs of a resistor-inductor 53748082Sbostic pair given the time step to take...that is, this routine takes a 53848082Sbostic time step for resistor-inductor pairs. The new outputs are found 53948082Sbostic by applying the trapezoidal rule.} 54048082Sbostic 54148082Sbosticprocedure RLPairStep(var rln: RLPAIR); 54248082Sbosticbegin 54348082Sbosticwith rln do 54448082Sbostic begin 54548082Sbostic if (time > lasttime) then 54648082Sbostic begin 54748082Sbostic lasttime := time; 54848082Sbostic invariant := xnext[xindex[1]] + (h / 2.0) * islope; 54948082Sbostic end; 55048082Sbostic islope := (y[yindex[1]] - y[yindex[2]] - r * xnext[xindex[1]]) / l; 55148082Sbostic xnext[xindex[1]] := invariant + (h / 2.0) * islope; 55248082Sbostic xnext[xindex[2]] := - xnext[xindex[1]]; 55348082Sbostic end; 55448082Sbosticend; 55548082Sbostic 55648082Sbostic 55748082Sbostic{The following procedure updates the outputs of a capacitor given the 55848082Sbostic time step...it takes the time step using a trapezoidal rule iteration.} 55948082Sbostic 56048082Sbosticprocedure CapacitorStep(var cn: CAPACITOR); 56148082Sbosticvar v: real; 56248082Sbosticbegin 56348082Sbosticwith cn do 56448082Sbostic begin 56548082Sbostic if (time > lasttime) then 56648082Sbostic begin 56748082Sbostic lasttime := time; 56848082Sbostic v := xnext[xindex[2]] - y[yindex[2]]; 56948082Sbostic invariant := v + (h / 2.0) * vslope; 57048082Sbostic end; 57148082Sbostic vslope := y[yindex[1]] / c; 57248082Sbostic v := invariant + (h / 2.0) * vslope; 57348082Sbostic xnext[xindex[1]] := - y[yindex[1]]; 57448082Sbostic xnext[xindex[2]] := y[yindex[2]] + v; 57548082Sbostic end; 57648082Sbosticend; 57748082Sbostic 57848082Sbostic 57948082Sbostic{The following procedure controls the overall x-step for the 58048082Sbostic specific circuit to be simulated.} 58148082Sbostic 58248082Sbosticprocedure XStep; 58348082Sbosticbegin 58448082SbosticVsourceStep(v1); 58548082SbosticRLPairStep(rl1); 58648082SbosticRLPairStep(rl2); 58748082SbosticCapacitorStep(c1); 58848082SbosticVsourceStep(ground); 58948082Sbosticend; 59048082Sbostic 59148082Sbostic 59248082Sbostic 59348082Sbostic 59448082Sbostic{The following procedure prints out the values of all the voltages and 59548082Sbostic currents for the circuit at each time step.} 59648082Sbostic 59748082Sbosticprocedure PrintReport; 59848082Sbosticbegin 59948082Sbosticwriteln(output); 60048082Sbosticwriteln(output); 60148082Sbosticwriteln(output,'REPORT at Time = ',time:8:5,' seconds'); 60248082Sbosticwriteln(output,'Number of iterations used: ',itcount:2); 60348082Sbosticwriteln(output,'Number of truncations: ',optimcount:2); 60448082Sbosticwriteln(output,'Number of Newton y-steps: ',newtoncount:2); 60548082Sbosticwriteln(output,'The voltages and currents are:'); 60648082Sbosticwriteln(output,' V1 = ',x[1]:12:7,' I1 = ',y[1]:12:7); 60748082Sbosticwriteln(output,' V2 = ',y[2]:12:7,' I2 = ',x[2]:12:7); 60848082Sbosticwriteln(output,' V3 = ',y[3]:12:7,' I3 = ',x[3]:12:7); 60948082Sbosticwriteln(output,' V4 = ',y[4]:12:7,' I4 = ',x[4]:12:7); 61048082Sbosticwriteln(output,' V5 = ',y[5]:12:7,' I5 = ',x[5]:12:7); 61148082Sbosticwriteln(output,' V6 = ',x[7]:12:7,' I6 = ',y[6]:12:7); 61248082Sbosticwriteln(output,' V7 = ',y[7]:12:7,' I7 = ',x[6]:12:7); 61348082Sbosticwriteln(output,' V8 = ',x[8]:12:7,' I8 = ',y[8]:12:7); 61448082Sbosticend; 61548082Sbostic 61648082Sbostic 61748082Sbostic 61848082Sbostic 61948082Sbostic{Finally, the main routine controls the whole simulation process.} 62048082Sbostic 62148082Sbosticbegin 62248082SbosticInitializeEverything; 62348082SbosticPrintReport; 62448082Sbosticfor timestep := 1 to maxsteps do 62548082Sbostic begin 62648082Sbostic itcount := 0; 62748082Sbostic optimcount := 0; 62848082Sbostic newtoncount := 0; 62948082Sbostic closenough := FALSE; 63048082Sbostic time := h * timestep; 63148082Sbostic repeat 63248082Sbostic begin 63348082Sbostic itcount := itcount + 1; 63448082Sbostic YStep; 63548082Sbostic XStep; 63648082Sbostic for update := 1 to N do 63748082Sbostic begin 63848082Sbostic x[update] := xnext[update]; 63948082Sbostic y[update] := ynext[update]; 64048082Sbostic end; 64148082Sbostic oldxnorm := newxnorm; 64248082Sbostic newxnorm := OneNorm(x); 64348082Sbostic if abs(newxnorm - oldxnorm) <= ROUGHLYZERO 64448082Sbostic then closenough := TRUE; 64548082Sbostic end; 64648082Sbostic if itcount < 4 then closenough := FALSE; 64748082Sbostic until (itcount = 25) or closenough; 64848082Sbostic PrintReport; 64948082Sbostic end; 65048082Sbosticend. 65148082Sbostic 652