|
|
1.1 root 1: subroutine dctran
2: implicit double precision (a-h,o-z)
3: c
4: c
5: c this routine controls the dc transfer curve, dc operating point,
6: c and transient analyses. the variables mode and modedc (defined below)
7: c determine exactly which analysis is performed.
8: c
9: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
10: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
11: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
12: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
13: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
14: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
15: common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad,
16: 1 defas,rstats(50),iwidth,lwidth,nopage
17: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
18: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
19: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
20: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
21: 2 itemno,nosolv,ipostp,iscrch
22: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
23: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
24: common /dc/ tcstar(2),tcstop(2),tcincr(2),icvflg,itcelm(2),kssop,
25: 1 kinel,kidin,kovar,kidout
26: common /tran/ tstep,tstop,tstart,delmax,tdmax,forfre,jtrflg
27: common /cje/ maxtim,itime,icost
28: common /blank/ value(1000)
29: integer nodplc(64)
30: complex*16 cvalue(32)
31: equivalence (value(1),nodplc(1),cvalue(1))
32: c
33: c
34: dimension subtit(4,2)
35: dimension avhdr(3),avfrm(4)
36: data aendor /9.87654321d+27/
37: data avhdr / 8h( (2x,a4, 8h,3x,a7,3, 5hx)//) /
38: data avfrm / 8h( (1h ,a, 8h1,i3,1h), 8h,f10.4,3, 4hx)/) /
39: data anode, avltg / 4hnode, 7hvoltage /
40: data subtit / 8hsmall si, 8hgnal bia, 8hs soluti, 8hon ,
41: 1 8hinitial , 8htransien, 8ht soluti, 8hon /
42: data lprn /1h(/
43: c
44: c the variables *mode*, *modedc*, and *initf* are used by spice to
45: c keep track of the state of the analysis. the values of these flags
46: c (and the corresponding meanings) are as follows:
47: c
48: c flag value meaning
49: c ---- ----- -------
50: c
51: c mode 1 dc analysis (subtype defined by *modedc*)
52: c 2 transient analysis
53: c 3 ac analysis (small signal)
54: c
55: c modedc 1 dc operating point
56: c 2 initial operating point for transient analysis
57: c 3 dc transfer curve computation
58: c
59: c initf 1 converge with 'off' devices allowed to float
60: c 2 initialize junction voltages
61: c 3 converge with 'off' devices held 'off'
62: c 4 store small-signal parameters away
63: c 5 first timepoint in transient analysis
64: c 6 prediction step
65: c
66: c note: *modedc* is only significant if *mode* = 1.
67: c
68: c
69: c initialize
70: c
71: call second(t1)
72: c.. don't take any chances with lx3, set to large number
73: lx3=20000000
74: lx2=20000000
75: nolx2=0
76: nolx3=0
77: loctim=5
78: c.. post-processing initialization
79: if(ipostp.eq.0) go to 1
80: numcur=jelcnt(9)
81: numpos=nunods+numcur
82: call getm8(ibuff,numpos)
83: numpos=numpos*4
84: if(numcur.eq.0) go to 1
85: loc=locate(9)
86: loccur=nodplc(loc+6)-1
87: c... set up format
88: 1 nvprln=4+(lwidth-72)/19
89: nvprln=min0(nvprln,ncnods-1)
90: ipos=2
91: call alfnum(nvprln,avfrm,ipos)
92: ipos=2
93: call alfnum(nvprln,avhdr,ipos)
94: c... allocate storage
95: if (mode.eq.2) go to 5
96: need=4*nstop+nut+nlt+nxtrm
97: call avlm8(navl)
98: if(need.le.navl) go to 4
99: c... not enough memory for dc operating point analysis
100: write(6,3) need,navl
101: 3 format('0insufficient memory available for dc analysis.',/
102: 1' memory required ',i6,', memory available ',i6,'.')
103: nogo=1
104: go to 1100
105: 4 call getm8(lvnim1,nstop)
106: call getm8(ndiag,nstop)
107: call getm8(lvn,nstop+nstop+nut+nlt)
108: call getm8(lx0,nxtrm)
109: if (modedc.ne.3) go to 15
110: 5 call getm8(lx1,nxtrm)
111: if(nolx2.eq.0) call getm8(lx2,nxtrm)
112: if (mode.ne.2) go to 12
113: if(nolx3.eq.0) call getm8(lx3,nxtrm)
114: call getm8(ltd,0)
115: 12 call getm8(loutpt,0)
116: 15 call crunch
117: lynl=lvn+nstop
118: lyu=lynl+nstop
119: lyl=lyu+nut
120: 20 if (mode.eq.2) go to 500
121: time=0.0d0
122: ag(1)=0.0d0
123: call sorupd
124: if (modedc.eq.3) go to 300
125: c
126: c .... single point dc analysis
127: c
128: c
129: c compute dc operating point
130: c
131: 100 initf=2
132: call iter8(itl1)
133: rstats(6)=rstats(6)+iterno
134: if (igoof.ne.0) go to 150
135: if (modedc.ne.1) go to 120
136: initf=4
137: call diode
138: call bjt
139: call jfet
140: call mosfet
141: c
142: c print operating point
143: c
144: 120 if ((mode.eq.1).and.(modedc.eq.2).and.(nosolv.ne.0)) go to 1000
145: call title(-1,lwidth,1,subtit(1,modedc))
146: write (6,avhdr) (anode,avltg,i=1,nvprln)
147: write (6,avfrm) (lprn,nodplc(junode+i),value(lvnim1+i),i=2,ncnods)
148: go to 1000
149: c
150: c no convergence
151: c
152: 150 nogo=1
153: write (6,151)
154: 151 format('1*error*: no convergence in dc analysis'/'0last node vol'
155: 1 ,'tages:'/)
156: write (6,avhdr) (anode,avltg,i=1,nvprln)
157: write (6,avfrm) (lprn,nodplc(junode+i),value(lvnim1+i),i=2,ncnods)
158: go to 1000
159: c
160: c .... dc transfer curves
161: c
162: 300 numout=jelcnt(41)+1
163: if(ipostp.ne.0) call pheadr(atitle)
164: itemp=itcelm(1)
165: locs=nodplc(itemp+1)
166: temval=value(locs+1)
167: icvfl2=1
168: if(itcelm(2).eq.0) go to 310
169: itemp=itcelm(2)
170: locs2=nodplc(itemp+1)
171: temv2=value(locs2+1)
172: value(locs2+1)=tcstar(2)
173: temp=dabs((tcstop(2)-tcstar(2))/tcincr(2))+0.5d0
174: icvfl2=idint(temp)+1
175: icvfl2=max0(icvfl2,1)
176: 310 delta=tcincr(1)
177: do 320 i=1,7
178: delold(i)=delta
179: 320 continue
180: icvfl1=icvflg/icvfl2
181: value(locs+1)=tcstar(1)
182: icalc=0
183: ical2=0
184: loctim=3
185: 340 initf=2
186: call iter8(itl1)
187: rstats(4)=rstats(4)+iterno
188: call copy8(value(lx0+1),value(lx1+1),nxtrm)
189: if(nolx2.eq.0) call copy8(value(lx0+1),value(lx2+1),nxtrm)
190: if (igoof.ne.0) go to 450
191: go to 360
192: 350 call getcje
193: if ((maxtim-itime).le.limtim) go to 460
194: initf=6
195: call iter8(itl2)
196: rstats(4)=rstats(4)+iterno
197: if (igoof.ne.0) go to 340
198: c
199: c store outputs
200: c
201: 360 call extmem(loutpt,numout)
202: loco=loutpt+icalc*numout
203: icalc=icalc+1
204: ical2=ical2+1
205: value(loco+1)=value(locs+1)
206: loc=locate(41)
207: 370 if (loc.eq.0) go to 400
208: if (nodplc(loc+5).ne.0) go to 380
209: node1=nodplc(loc+2)
210: node2=nodplc(loc+3)
211: iseq=nodplc(loc+4)
212: value(loco+iseq)=value(lvnim1+node1)-value(lvnim1+node2)
213: loc=nodplc(loc)
214: go to 370
215: 380 iptr=nodplc(loc+2)
216: iptr=nodplc(iptr+6)
217: iseq=nodplc(loc+4)
218: value(loco+iseq)=value(lvnim1+iptr)
219: loc=nodplc(loc)
220: go to 370
221: c
222: c increment source value
223: c
224: 400 if(ipostp.eq.0) go to 410
225: value(ibuff+1)=value(locs+1)
226: call copy8(value(lvnim1+2),value(ibuff+2),nunods-1)
227: if(numcur.ne.0) call copy8(value(lvnim1+loccur+1),
228: 1 value(ibuff+nunods+1),numcur)
229: call fwrite(value(ibuff+1),numpos)
230: 410 if (icalc.ge.icvflg) go to 490
231: if(ical2.ge.icvfl1) go to 480
232: if(nolx2.ne.0) go to 420
233: call ptrmem(lx2,itemp)
234: call ptrmem(lx1,lx2)
235: go to 430
236: 420 call ptrmem(lx1,itemp)
237: 430 call ptrmem(lx0,lx1)
238: call ptrmem(itemp,lx0)
239: value(locs+1)=tcstar(1)+dfloat(ical2)*delta
240: go to 350
241: c
242: c no convergence
243: c
244: 450 itemp=itcelm(1)
245: loce=nodplc(itemp+1)
246: write (6,451) value(loce),value(locs+1)
247: 451 format('1*error*: no convergence in dc transfer curves at ',a8,
248: 1 ' = ',1pd10.3/'0last node voltages:'/)
249: write (6,avhdr) (anode,avltg,i=1,nvprln)
250: write (6,avfrm) (lprn,nodplc(junode+i),value(lvnim1+i),i=2,ncnods)
251: go to 470
252: 460 write (6,461)
253: 461 format('0*error*: cpu time limit exceeded ... analysis stopped'/)
254: 470 nogo=1
255: go to 490
256: c... reset first sweep variable ... step second
257: 480 ical2=0
258: value(locs+1)=tcstar(1)
259: value(locs2+1)=value(locs2+1)+tcincr(2)
260: go to 340
261: c
262: c finished with dc transfer curves
263: c
264: 490 value(locs+1)=temval
265: if(itcelm(2).ne.0) value(locs2+1)=temv2
266: if(ipostp.eq.0) go to 1000
267: value(ibuff+1)=aendor
268: call fwrite(value(ibuff+1),numpos)
269: go to 1000
270: c
271: c .... transient analysis
272: c
273: 500 numout=jelcnt(42)+1
274: if(ipostp.ne.0) call pheadr(atitle)
275: numese=jelcnt(2)+jelcnt(3)+jelcnt(11)+jelcnt(12)+jelcnt(13)
276: 1 +jelcnt(14)
277: if (numese.eq.0) delmax=dmin1(delmax,tstep)
278: initf=5
279: iord=1
280: loctim=9
281: icalc=0
282: numtp=0
283: numrtp=0
284: numnit=0
285: time=0.0d0
286: ibkflg=1
287: delbkp=delmax
288: nbkpt=1
289: delta=delmax
290: do 510 i=1,7
291: delold(i)=delta
292: 510 continue
293: delmin=1.0d-9*delmax
294: go to 650
295: c
296: c increment time, update sources, and solve next timepoint
297: c
298: 600 time=time+delta
299: call sorupd
300: if (nogo.ne.0) go to 950
301: call getcje
302: if ((maxtim-itime).le.limtim) go to 920
303: if ((itl5.ne.0).and.(numnit.ge.itl5)) go to 905
304: call comcof
305: if (initf.ne.5) initf=6
306: itrlim=itl4
307: if ((numtp.eq.0).and.(nosolv.ne.0)) itrlim=itl1
308: call iter8(itrlim)
309: if(itl5.ne.0) numnit=numnit+iterno
310: numtp=numtp+1
311: if (numtp.ne.1) go to 605
312: if(nolx2.eq.0) call copy8(value(lx1+1),value(lx2+1),nxtrm)
313: if(nolx3.eq.0) call copy8(value(lx1+1),value(lx3+1),nxtrm)
314: c.. note that time-point is cut when itrlim exceeded regardless
315: c.. of which time-step contol is specified thru 'lvltim'.
316: 605 if (igoof.eq.0) go to 610
317: jord=iord
318: iord=1
319: if (jord.ge.5) call clrmem(lx7)
320: if (jord.ge.4) call clrmem(lx6)
321: if (jord.ge.3) call clrmem(lx5)
322: if ((jord.ge.2).and.(method.ne.1)) call clrmem(lx4)
323: igoof=0
324: time=time-delta
325: delta=delta/8.0d0
326: go to 620
327: 610 delnew=delta
328: if (numtp.eq.1) go to 630
329: call trunc(delnew)
330: if (delnew.ge.(0.9d0*delta)) go to 630
331: time=time-delta
332: delta=delnew
333: 620 numrtp=numrtp+1
334: ibkflg=0
335: delold(1)=delta
336: if (delta.ge.delmin) go to 600
337: time=time+delta
338: go to 900
339: c.. time-point accepted
340: 630 call copy8(delold(1),delold(2),6)
341: delta=delnew
342: delold(1)=delta
343: c
344: c determine order of integration method
345: c
346: c... skip if trapezoidal algorithm used
347: if ((method.eq.1).and.(iord.eq.2)) go to 650
348: if (numtp.eq.1) go to 650
349: ordrat=1.05d0
350: if (iord.gt.1) go to 635
351: iord=2
352: call trunc(delnew)
353: iord=1
354: if ((delnew/delta).le.ordrat) go to 650
355: if (maxord.le.1) go to 650
356: iord=2
357: if (method.eq.1) go to 650
358: call getm8(lx4,nxtrm)
359: go to 650
360: 635 if (iord.lt.maxord) go to 640
361: iord=iord-1
362: call trunc(delnew)
363: iord=iord+1
364: if ((delnew/delta).le.ordrat) go to 650
365: go to 642
366: 640 iord=iord-1
367: call trunc(delnew)
368: iord=iord+1
369: if ((delnew/delta).le.ordrat) go to 645
370: 642 iord=iord-1
371: if (iord.eq.1) call clrmem(lx4)
372: if (iord.eq.2) call clrmem(lx5)
373: if (iord.eq.3) call clrmem(lx6)
374: if (iord.eq.4) call clrmem(lx7)
375: go to 650
376: 645 iord=iord+1
377: call trunc(delnew)
378: iord=iord-1
379: if ((delnew/delta).le.ordrat) go to 650
380: iord=iord+1
381: if (iord.eq.2) call getm8(lx4,nxtrm)
382: if (iord.eq.3) call getm8(lx5,nxtrm)
383: if (iord.eq.4) call getm8(lx6,nxtrm)
384: if (iord.eq.5) call getm8(lx7,nxtrm)
385: c
386: c store outputs
387: c
388: 650 if ((time+delta).le.tstart) go to 685
389: if ((numtp.eq.0).and.(nosolv.ne.0)) go to 685
390: call extmem(loutpt,numout)
391: loco=loutpt+icalc*numout
392: icalc=icalc+1
393: value(loco+1)=time
394: loc=locate(42)
395: 670 if (loc.eq.0) go to 682
396: if (nodplc(loc+5).ne.0) go to 680
397: node1=nodplc(loc+2)
398: node2=nodplc(loc+3)
399: iseq=nodplc(loc+4)
400: value(loco+iseq)=value(lvnim1+node1)-value(lvnim1+node2)
401: loc=nodplc(loc)
402: go to 670
403: 680 iptr=nodplc(loc+2)
404: iptr=nodplc(iptr+6)
405: iseq=nodplc(loc+4)
406: value(loco+iseq)=value(lvnim1+iptr)
407: loc=nodplc(loc)
408: go to 670
409: 682 if(ipostp.eq.0) go to 684
410: value(ibuff+1)=time
411: call copy8(value(lvnim1+2),value(ibuff+2),nunods-1)
412: if(numcur.ne.0) call copy8(value(lvnim1+loccur+1),
413: 1 value(ibuff+nunods+1),numcur)
414: call fwrite(value(ibuff+1),numpos)
415: 684 continue
416: 685 if (jelcnt(17).eq.0) go to 694
417: call sizmem(ltd,ltdsiz)
418: numtd=ltdsiz/ntlin
419: if (numtd.le.3) go to 689
420: baktim=time-tdmax
421: if (baktim.lt.0.0d0) go to 689
422: lcntr=0
423: ltemp=ltd
424: do 686 i=1,numtd
425: if (value(ltemp+1).ge.baktim) go to 687
426: ltemp=ltemp+ntlin
427: lcntr=lcntr+1
428: 686 continue
429: go to 689
430: 687 if (lcntr.le.2) go to 689
431: lcntr=lcntr-2
432: nwords=lcntr*ntlin
433: ltemp=ltemp-ntlin-ntlin
434: call copy8(value(ltemp+1),value(ltd+1),ltdsiz-nwords)
435: call relmem(ltd,nwords)
436: call sizmem(ltd,ltdsiz)
437: 689 call extmem(ltd,ntlin)
438: ltdptr=ltd+ltdsiz
439: value(ltdptr+1)=time
440: loc=locate(17)
441: 690 if (loc.eq.0) go to 693
442: locv=nodplc(loc+1)
443: z0=value(locv+1)
444: node1=nodplc(loc+2)
445: node2=nodplc(loc+3)
446: node3=nodplc(loc+4)
447: node4=nodplc(loc+5)
448: ibr1=nodplc(loc+8)
449: ibr2=nodplc(loc+9)
450: lspot=nodplc(loc+30)+ltdptr
451: if ((initf.eq.5).and.(nosolv.ne.0)) go to 691
452: value(lspot)=value(lvnim1+node3)-value(lvnim1+node4)
453: 1 +value(lvnim1+ibr2)*z0
454: value(lspot+1)=value(lvnim1+node1)-value(lvnim1+node2)
455: 1 +value(lvnim1+ibr1)*z0
456: go to 692
457: 691 value(lspot)=value(locv+7)+value(locv+8)*z0
458: value(lspot+1)=value(locv+5)+value(locv+6)*z0
459: 692 loc=nodplc(loc)
460: go to 690
461: c
462: c add two *fake* backpoints to ltd for interpolation near time=0.0d0
463: c
464: 693 if (numtd.ne.0) go to 694
465: call extmem(ltd,ntlin+ntlin)
466: call copy8(value(ltd+1),value(ltd+ntlin+1),ntlin)
467: call copy8(value(ltd+1),value(ltd+2*ntlin+1),ntlin)
468: value(ltd+2*ntlin+1)=time
469: value(ltd+ntlin+1)=time-delta
470: value(ltd+1)=time-delta-delta
471: c
472: c rotate state vector storage
473: c
474: 694 go to (710,706,702,698,696,696), iord
475: 696 call ptrmem(lx7,itemp)
476: call ptrmem(lx6,lx7)
477: go to 700
478: 698 call ptrmem(lx6,itemp)
479: 700 call ptrmem(lx5,lx6)
480: go to 704
481: 702 call ptrmem(lx5,itemp)
482: 704 call ptrmem(lx4,lx5)
483: go to 708
484: 706 if (method.eq.1) go to 710
485: call ptrmem(lx4,itemp)
486: 708 call ptrmem(lx3,lx4)
487: go to 713
488: 710 if(nolx3.eq.0) go to 712
489: if(nolx2.eq.0) go to 711
490: call ptrmem(lx1,itemp)
491: go to 714
492: 711 call ptrmem(lx2,itemp)
493: call ptrmem(lx1,lx2)
494: go to 714
495: 712 call ptrmem(lx3,itemp)
496: 713 call ptrmem(lx2,lx3)
497: call ptrmem(lx1,lx2)
498: 714 call ptrmem(lx0,lx1)
499: call ptrmem(itemp,lx0)
500: c
501: c check breakpoints
502: c
503: 750 if (ibkflg.eq.0) go to 760
504: c.. just accepted analysis at breakpoint
505: jord=iord
506: iord=1
507: if (jord.ge.5) call clrmem(lx7)
508: if (jord.ge.4) call clrmem(lx6)
509: if (jord.ge.3) call clrmem(lx5)
510: if ((jord.ge.2).and.(method.ne.1)) call clrmem(lx4)
511: ibkflg=0
512: nbkpt=nbkpt+1
513: if (nbkpt.gt.numbkp) go to 950
514: temp=dmin1(delbkp,value(lsbkpt+nbkpt)-time)
515: delta=dmin1(delta,0.1d0*temp,delmax)
516: if (numtp.eq.0) delta=delta/10.0d0
517: delold(1)=delta
518: go to 600
519: 760 del1=value(lsbkpt+nbkpt)-time
520: if ((1.01d0*delta).le.del1) go to 600
521: ibkflg=1
522: delbkp=delta
523: delta=del1
524: delold(1)=delta
525: go to 600
526: c
527: c transient analysis failed
528: c
529: 900 write (6,901)
530: 901 format('1*error*: internal timestep too small in transient analys
531: 1is'/)
532: go to 910
533: 905 write (6,906) itl5
534: 906 format('1*error*: transient analysis iterations exceed limit of '
535: 1,i5,/'0this limit may be overridden using the itl5 parameter on th
536: 2e .option card')
537: 910 write (6,911) time,delta,numnit
538: 911 format(1h0,10x,'time = ',1pd12.5,'; delta = ',d12.5,'; numnit =
539: 1',i6/)
540: write (6,916)
541: 916 format(1h0/'0last node voltages:'/)
542: write (6,avhdr) (anode,avltg,i=1,nvprln)
543: write (6,avfrm) (lprn,nodplc(junode+i),value(lvnim1+i),i=2,ncnods)
544: go to 930
545: 920 write (6,921) time
546: 921 format('0*error*: cpu time limit exceeded in transient analysis '
547: 1 ,'at time = ',1pd13.6/)
548: 930 nogo=1
549: c
550: c finished with transient analysis
551: c
552: 950 rstats(10)=rstats(10)+numnit
553: rstats(30)=rstats(30)+numtp
554: rstats(31)=rstats(31)+numrtp
555: rstats(32)=rstats(32)+numnit
556: if(ipostp.eq.0) go to 1000
557: value(ibuff+1)=aendor
558: call fwrite(value(ibuff+1),numpos)
559: c
560: c return unneeded memory
561: c
562: 1000 if (mode.eq.2) go to 1010
563: if (modedc.ne.3) go to 1100
564: 1010 call clrmem(lvnim1)
565: call clrmem(lx0)
566: call clrmem(ndiag)
567: call clrmem(lvn)
568: call clrmem(lx1)
569: if(nolx2.eq.0) call clrmem(lx2)
570: if ((mode.eq.1).and.(modedc.eq.3)) go to 1020
571: if(nolx3.eq.0) call clrmem(lx3)
572: if (mode.eq.1) go to 1020
573: call clrmem(ltd)
574: if (iord.eq.1) go to 1020
575: if (method.eq.1) go to 1020
576: call clrmem(lx4)
577: if (iord.eq.2) go to 1020
578: call clrmem(lx5)
579: if (iord.eq.3) go to 1020
580: call clrmem(lx6)
581: if (iord.eq.4) go to 1020
582: call clrmem(lx7)
583: 1020 call extmem(loutpt,2*numout)
584: 1100 if(ipostp.ne.0) call clrmem(ibuff)
585: call second(t2)
586: rstats(loctim)=rstats(loctim)+t2-t1
587: return
588: end
589: subroutine fwrite(iarray,numwds)
590: c
591: c write onto 'punch' file numwds 16-bit words starting
592: c with location iarray(/1/)
593: c
594: integer iarray(1)
595: c
596: c... data must be written out in 40 word (80 byte) chunks
597: c
598: integer idata(20)
599: numwd4=(numwds+1)/2
600: numblk=(numwd4-1)/20+1
601: kntr=1
602: numlft=numwd4
603: do 10 i=1,numblk
604: kstop=min0(numlft,20)
605: call copy4(iarray(kntr),idata(1),kstop)
606: write(7) idata
607: kntr=kntr+20
608: numlft=numlft-20
609: 10 continue
610: return
611: end
612: subroutine pheadr(aheadr)
613: implicit double precision (a-h,o-z)
614: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
615: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
616: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
617: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
618: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
619: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
620: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
621: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
622: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
623: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
624: 2 itemno,nosolv,ipostp,iscrch
625: common /dc/ tcstar(2),tcstop(2),tcincr(2),icvflg,itcelm(2),kssop,
626: 1 kinel,kidin,kovar,kidout
627: common /miscel/ atime,aprog(3),adate,atitle(10),defl,defw,defad,
628: 1 defas,rstats(50),iwidth,lwidth,nopage
629: common /blank/ value(1000)
630: integer nodplc(64)
631: complex*16 cvalue(32)
632: integer*2 int2,nodpl2(128)
633: equivalence (value(1),nodpl2(1))
634: equivalence (value(1),nodplc(1),cvalue(1))
635: dimension aheadr(10)
636: c
637: c put out the header records onto the post-processing file
638: c routine is used for all analysis modes (mode=1,2,3)
639: c
640: dimension xtype(2)
641: data xtype /4htime,4hfreq/
642: data ablnk,aletv,aleti /1h ,1hv,1hi/
643: call getm8(ibuff,12)
644: call copy8(aheadr(1),value(ibuff+1),10)
645: value(ibuff+11)=adate
646: value(ibuff+12)=atime
647: call fwrite(value(ibuff+1),48)
648: numout=nunods+jelcnt(9)
649: info=3
650: call getm8(inames,numout)
651: call getm4(itypes,numout)
652: call getm4(iseqs,numout)
653: itype2=itypes*2
654: iseq2=iseqs*2
655: iknt=1
656: nodpl2(iseq2+1)=1
657: if(mode.ne.1) go to 10
658: loc=itcelm(1)
659: locv=nodplc(loc+1)
660: value(inames+1)=value(locv)
661: anam=ablnk
662: call move(anam,1,value(locv),1,1)
663: ityp=0
664: if(anam.eq.aletv) ityp=3
665: if(anam.eq.aleti) ityp=4
666: nodpl2(itype2+1)=ityp
667: go to 20
668: 10 value(inames+1)=xtype(mode-1)
669: nodpl2(itype2+1)=mode-1
670: 20 do 30 i=2,nunods
671: nodpl2(itype2+i)=3
672: nodpl2(iseq2+i)=i
673: value(inames+i)=ablnk
674: ipos=1
675: call alfnum(nodplc(junode+i),value(inames+i),ipos)
676: 30 continue
677: loc=locate(9)
678: iknt=nunods
679: 40 if(loc.eq.0) go to 50
680: iknt=iknt+1
681: nodpl2(itype2+iknt)=4
682: nodpl2(iseq2+iknt)=iknt
683: locv=nodplc(loc+1)
684: value(inames+iknt)=value(locv)
685: loc=nodplc(loc)
686: go to 40
687: 50 int2=numout
688: call fwrite(int2,1)
689: int2=info
690: call fwrite(int2,1)
691: nwds=numout*4
692: call fwrite(value(inames+1),nwds)
693: call fwrite(nodpl2(itype2+1),numout)
694: call fwrite(nodpl2(iseq2+1),numout)
695: call clrmem(ibuff)
696: call clrmem(inames)
697: call clrmem(itypes)
698: call clrmem(iseqs)
699: return
700: end
701: subroutine comcof
702: implicit double precision (a-h,o-z)
703: c
704: c this routine calculates the timestep-dependent terms used in the
705: c numerical integration.
706: c
707: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
708: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
709: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
710: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
711: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
712: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
713: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
714: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
715: 2 itemno,nosolv,ipostp,iscrch
716: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
717: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
718: common /blank/ value(1000)
719: integer nodplc(64)
720: complex*16 cvalue(32)
721: equivalence (value(1),nodplc(1),cvalue(1))
722: dimension gmat(7,7)
723: c
724: c compute coefficients for particular integration method
725: c
726: if (method.ne.1) go to 5
727: if (iord.eq.1) go to 5
728: c... trapezoidal method
729: ag(1)=1.0d0/delta/(1.0d0-xmu)
730: ag(2)=xmu/(1.0d0-xmu)
731: go to 200
732: c
733: c construct gear coefficient matrix
734: c
735: 5 istop=iord+1
736: call zero8(ag,istop)
737: ag(2)=-1.0d0
738: do 10 i=1,istop
739: gmat(1,i)=1.0d0
740: 10 continue
741: do 20 i=2,istop
742: gmat(i,1)=0.0d0
743: 20 continue
744: arg=0.0d0
745: do 40 i=2,istop
746: arg=arg+delold(i-1)
747: arg1=1.0d0
748: do 30 j=2,istop
749: arg1=arg1*arg
750: gmat(j,i)=arg1
751: 30 continue
752: 40 continue
753: c
754: c solve for gear coefficients ag(*)
755: c
756: c
757: c lu decomposition
758: c
759: do 70 i=2,istop
760: jstart=i+1
761: if (jstart.gt.istop) go to 70
762: do 60 j=jstart,istop
763: gmat(j,i)=gmat(j,i)/gmat(i,i)
764: do 50 k=jstart,istop
765: gmat(j,k)=gmat(j,k)-gmat(j,i)*gmat(i,k)
766: 50 continue
767: 60 continue
768: 70 continue
769: c
770: c forward substitution
771: c
772: do 90 i=2,istop
773: jstart=i+1
774: if (jstart.gt.istop) go to 90
775: do 80 j=jstart,istop
776: ag(j)=ag(j)-gmat(j,i)*ag(i)
777: 80 continue
778: 90 continue
779: c
780: c backward substitution
781: c
782: ag(istop)=ag(istop)/gmat(istop,istop)
783: ir=istop
784: do 110 i=2,istop
785: jstart=ir
786: ir=ir-1
787: do 100 j=jstart,istop
788: ag(ir)=ag(ir)-gmat(ir,j)*ag(j)
789: 100 continue
790: ag(ir)=ag(ir)/gmat(ir,ir)
791: 110 continue
792: c
793: c finished
794: c
795: 200 return
796: end
797: subroutine trunc(delnew)
798: implicit double precision (a-h,o-z)
799: c
800: c this routine determines the new transient stepsize by either
801: c calling terr to estimate the local truncation error, or by checking
802: c on the number of iterations needed to converge at the last timepoint.
803: c
804: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
805: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
806: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
807: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
808: 2 itemno,nosolv,ipostp,iscrch
809: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
810: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
811: common /tran/ tstep,tstop,tstart,delmax,tdmax,forfre,jtrflg
812: common /blank/ value(1000)
813: integer nodplc(64)
814: complex*16 cvalue(32)
815: equivalence (value(1),nodplc(1),cvalue(1))
816: c
817: c
818: if (lvltim.ne.0) go to 5
819: delnew=dmin1(tstep,delmax)
820: return
821: 5 if (lvltim.ne.1) go to 10
822: delnew=delta
823: if (iterno.gt.itl3) return
824: delnew=dmin1(2.0d0*delta,tstep,delmax)
825: return
826: c
827: c capacitors
828: c
829: 10 delnew=1.0d20
830: loc=locate(2)
831: 20 if (loc.eq.0) go to 30
832: loct=nodplc(loc+8)
833: call terr(loct,delnew)
834: loc=nodplc(loc)
835: go to 20
836: c
837: c inductors
838: c
839: 30 loc=locate(3)
840: 40 if (loc.eq.0) go to 50
841: loct=nodplc(loc+11)
842: call terr(loct,delnew)
843: loc=nodplc(loc)
844: go to 40
845: c
846: c diodes
847: c
848: 50 loc=locate(11)
849: 60 if (loc.eq.0) go to 70
850: loct=nodplc(loc+11)
851: call terr(loct+3,delnew)
852: loc=nodplc(loc)
853: go to 60
854: c
855: c bjts
856: c
857: 70 loc=locate(12)
858: 80 if (loc.eq.0) go to 90
859: loct=nodplc(loc+22)
860: call terr(loct+8,delnew)
861: call terr(loct+10,delnew)
862: call terr(loct+12,delnew)
863: loc=nodplc(loc)
864: go to 80
865: c
866: c jfets
867: c
868: 90 loc=locate(13)
869: 100 if (loc.eq.0) go to 110
870: loct=nodplc(loc+19)
871: call terr(loct+9,delnew)
872: call terr(loct+11,delnew)
873: loc=nodplc(loc)
874: go to 100
875: c
876: c mosfets
877: c
878: 110 loc=locate(14)
879: 120 if (loc.eq.0) go to 200
880: loct=nodplc(loc+26)
881: call terr(loct+12,delnew)
882: call terr(loct+14,delnew)
883: call terr(loct+16,delnew)
884: call terr(loct+18,delnew)
885: call terr(loct+20,delnew)
886: loc=nodplc(loc)
887: go to 120
888: c
889: c delta is allowed only to double at each timepoint
890: c
891: 200 delnew=dmin1(2.0d0*delta,delnew,delmax)
892: return
893: end
894: subroutine terr(loct,delnew)
895: implicit double precision (a-h,o-z)
896: c
897: c this routine estimates the local truncation error for a particular
898: c circuit element. it then computes the appropriate stepsize which
899: c should be used.
900: c
901: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
902: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
903: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
904: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
905: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
906: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
907: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
908: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
909: 2 itemno,nosolv,ipostp,iscrch
910: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
911: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
912: common /blank/ value(1000)
913: integer nodplc(64)
914: complex*16 cvalue(32)
915: equivalence (value(1),nodplc(1),cvalue(1))
916: c
917: c
918: dimension qcap(1),ccap(1),diff(8),deltmp(7),coef(6)
919: equivalence (qcap(1),value(1)),(ccap(1),value(2))
920: data coef / 5.000000000d-1, 2.222222222d-1, 1.363636364d-1,
921: 1 9.600000000d-2, 7.299270073d-2, 5.830903790d-2 /
922: data xtwelv / 8.333333333d-2 /
923: c
924: c
925: tol=reltol*dmax1(dabs(ccap(lx0+loct)),dabs(ccap(lx1+loct)))+abstol
926: ctol=reltol*dmax1(dabs(qcap(lx0+loct)),dabs(qcap(lx1+loct)),
927: 1 chgtol)/delta
928: tol=dmax1(tol,ctol)
929: c
930: c determine divided differences
931: c
932: go to (6,5,4,3,2,1), iord
933: 1 diff(8)=qcap(lx7+loct)
934: 2 diff(7)=qcap(lx6+loct)
935: 3 diff(6)=qcap(lx5+loct)
936: 4 diff(5)=qcap(lx4+loct)
937: 5 diff(4)=qcap(lx3+loct)
938: 6 diff(3)=qcap(lx2+loct)
939: diff(2)=qcap(lx1+loct)
940: diff(1)=qcap(lx0+loct)
941: istop=iord+1
942: do 10 i=1,istop
943: deltmp(i)=delold(i)
944: 10 continue
945: 20 do 30 i=1,istop
946: diff(i)=(diff(i)-diff(i+1))/deltmp(i)
947: 30 continue
948: istop=istop-1
949: if (istop.eq.0) go to 100
950: do 40 i=1,istop
951: deltmp(i)=deltmp(i+1)+delold(i)
952: 40 continue
953: go to 20
954: c
955: c diff(1) contains divided difference
956: c
957: 100 const=coef(iord)
958: if ((method.eq.1).and.(iord.eq.2)) const=xtwelv
959: del=trtol*tol/dmax1(abstol,const*dabs(diff(1)))
960: if (iord.eq.1) go to 200
961: if (iord.ge.3) go to 150
962: del=dsqrt(del)
963: go to 200
964: 150 del=dexp(dlog(del)/dfloat(iord))
965: 200 delnew=dmin1(delnew,del)
966: return
967: end
968: subroutine sorupd
969: implicit double precision (a-h,o-z)
970: c
971: c this routine updates the independent voltage and current sources
972: c used in the circuit. it also updates the ltd table (which contains
973: c previous (delayed) values of the sources used to model transmission
974: c lines).
975: c
976: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
977: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
978: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
979: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
980: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
981: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
982: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
983: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
984: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
985: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
986: 2 itemno,nosolv,ipostp,iscrch
987: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
988: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
989: common /blank/ value(1000)
990: integer nodplc(64)
991: complex*16 cvalue(32)
992: equivalence (value(1),nodplc(1),cvalue(1))
993: c
994: c
995: do 500 id=9,10
996: loc=locate(id)
997: 10 if (loc.eq.0) go to 500
998: locv=nodplc(loc+1)
999: locp=nodplc(loc+5)
1000: itype=nodplc(loc+4)+1
1001: go to (490,100,200,300,400,450), itype
1002: c
1003: c pulse source
1004: c
1005: 100 v1=value(locp+1)
1006: v2=value(locp+2)
1007: t1=value(locp+3)
1008: t2=value(locp+4)
1009: t3=value(locp+5)
1010: t4=value(locp+6)
1011: period=value(locp+7)
1012: time1=time
1013: if (time1.le.0.0d0) go to 160
1014: 110 if (time1.lt.t1+period) go to 120
1015: time1=time1-period
1016: go to 110
1017: 120 if (time1.lt.t4) go to 130
1018: value(locv+1)=v1
1019: go to 490
1020: 130 if (time1.lt.t3) go to 140
1021: value(locv+1)=v2+(time1-t3)*(v1-v2)/(t4-t3)
1022: go to 490
1023: 140 if (time1.lt.t2) go to 150
1024: value(locv+1)=v2
1025: go to 490
1026: 150 if (time1.lt.t1) go to 160
1027: value(locv+1)=v1+(time1-t1)*(v2-v1)/(t2-t1)
1028: go to 490
1029: 160 value(locv+1)=v1
1030: go to 490
1031: c
1032: c sinusoidal source
1033: c
1034: 200 v1=value(locp+1)
1035: v2=value(locp+2)
1036: omeg=value(locp+3)
1037: t1=value(locp+4)
1038: theta=value(locp+5)
1039: time1=time-t1
1040: if (time1.gt.0.0d0) go to 210
1041: value(locv+1)=v1
1042: go to 490
1043: 210 if (theta.ne.0.0d0) go to 220
1044: value(locv+1)=v1+v2*dsin(omeg*time1)
1045: go to 490
1046: 220 value(locv+1)=v1+v2*dsin(omeg*time1)*dexp(-time1*theta)
1047: go to 490
1048: c
1049: c exponential source
1050: c
1051: 300 v1=value(locp+1)
1052: v2=value(locp+2)
1053: t1=value(locp+3)
1054: tau1=value(locp+4)
1055: t2=value(locp+5)
1056: tau2=value(locp+6)
1057: time1=time
1058: if (time1.gt.t1) go to 310
1059: value(locv+1)=v1
1060: go to 490
1061: 310 if (time1.gt.t2) go to 320
1062: value(locv+1)=v1+(v2-v1)*(1.0d0-dexp((t1-time1)/tau1))
1063: go to 490
1064: 320 value(locv+1)=v1+(v2-v1)*(1.0d0-dexp((t1-time1)/tau1))
1065: 1 +(v1-v2)*(1.0d0-dexp((t2-time1)/tau2))
1066: go to 490
1067: c
1068: c piecewise-linear source
1069: c
1070: 400 t1=value(locp+1)
1071: v1=value(locp+2)
1072: t2=value(locp+3)
1073: v2=value(locp+4)
1074: iknt=4
1075: 410 if (time.le.t2) go to 420
1076: t1=t2
1077: v1=v2
1078: t2=value(locp+iknt+1)
1079: v2=value(locp+iknt+2)
1080: iknt=iknt+2
1081: go to 410
1082: 420 value(locv+1)=v1+((time-t1)/(t2-t1))*(v2-v1)
1083: go to 490
1084: c
1085: c single-frequency fm
1086: c
1087: 450 v1=value(locp+1)
1088: v2=value(locp+2)
1089: omegc=value(locp+3)
1090: xmod=value(locp+4)
1091: omegs=value(locp+5)
1092: value(locv+1)=v1+v2*dsin(omegc*time+xmod*dsin(omegs*time))
1093: 490 loc=nodplc(loc)
1094: go to 10
1095: 500 continue
1096: c
1097: c update transmission line sources
1098: c
1099: if (jelcnt(17).eq.0) go to 1000
1100: if (mode.ne.2) go to 1000
1101: call sizmem(ltd,ltdsiz)
1102: numtd=ltdsiz/ntlin
1103: if (numtd.lt.3) go to 900
1104: loc=locate(17)
1105: 610 if (loc.eq.0) go to 1000
1106: locv=nodplc(loc+1)
1107: td=value(locv+2)
1108: baktim=time-td
1109: if (baktim.lt.0.0d0) go to 640
1110: ltdptr=nodplc(loc+30)
1111: icntr=2
1112: l1=ltd
1113: l2=l1+ntlin
1114: l3=l2+ntlin
1115: t1=value(l1+1)
1116: t2=value(l2+1)
1117: 620 t3=value(l3+1)
1118: icntr=icntr+1
1119: if (baktim.le.t3) go to 630
1120: if (icntr.eq.numtd) go to 900
1121: l1=l2
1122: l2=l3
1123: l3=l2+ntlin
1124: t1=t2
1125: t2=t3
1126: go to 620
1127: 630 dt1t2=t1-t2
1128: dt1t3=t1-t3
1129: dt2t3=t2-t3
1130: tdnom1=1.0d0/(dt1t2*dt1t3)
1131: tdnom2=-1.0d0/(dt1t2*dt2t3)
1132: tdnom3=1.0d0/(dt2t3*dt1t3)
1133: dtt1=baktim-t1
1134: dtt2=baktim-t2
1135: dtt3=baktim-t3
1136: tfact1=dtt2*dtt3*tdnom1
1137: tfact2=dtt1*dtt3*tdnom2
1138: tfact3=dtt1*dtt2*tdnom3
1139: value(locv+3)=value(l1+ltdptr+0)*tfact1+value(l2+ltdptr+0)*tfact2
1140: 1 +value(l3+ltdptr+0)*tfact3
1141: value(locv+4)=value(l1+ltdptr+1)*tfact1+value(l2+ltdptr+1)*tfact2
1142: 1 +value(l3+ltdptr+1)*tfact3
1143: 640 loc=nodplc(loc)
1144: go to 610
1145: c
1146: c internal logic error: less than 3 entries in ltd
1147: c
1148: 900 nogo=1
1149: write (6,901) numtd,icntr
1150: 901 format('0*abort*: internal spice error: sorupd: ',2i5/)
1151: c
1152: c finished
1153: c
1154: 1000 return
1155: end
1156: subroutine iter8(itlim)
1157: implicit double precision (a-h,o-z)
1158: c
1159: c this routine drives the newton-raphson iteration technique used to
1160: c solve the set of nonlinear circuit equations.
1161: c
1162: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1163: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
1164: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
1165: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
1166: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
1167: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
1168: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
1169: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
1170: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1171: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
1172: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
1173: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
1174: 2 itemno,nosolv,ipostp,iscrch
1175: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1176: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
1177: common /blank/ value(1000)
1178: integer nodplc(64)
1179: complex*16 cvalue(32)
1180: equivalence (value(1),nodplc(1),cvalue(1))
1181: c
1182: c
1183: igoof=0
1184: iterno=0
1185: ndrflo=0
1186: noncon=0
1187: ipass=0
1188: c
1189: c construct linear equations and check convergence
1190: c
1191: 10 call load
1192: if ((mode.eq.1).and.(modedc.eq.2).and.(nosolv.ne.0)) go to 300
1193: iterno=iterno+1
1194: go to (20,30,40,50,50,50),initf
1195: 20 if(mode.ne.1) go to 22
1196: call sizmem(nsnod,nic)
1197: if(nic.eq.0) go to 22
1198: if(ipass.ne.0) noncon=ipass
1199: ipass=0
1200: 22 if(noncon.eq.0) go to 300
1201: go to 100
1202: 30 initf=3
1203: 40 if (noncon.eq.0) initf=1
1204: ipass=1
1205: go to 100
1206: 50 initf=1
1207: c
1208: c solve equations for next iteration
1209: c
1210: 100 if (iterno.ge.itlim) go to 200
1211: 110 call dcdcmp
1212: call dcsol
1213: 120 if (igoof.eq.0) go to 130
1214: ndrflo=ndrflo+1
1215: igoof=0
1216: 130 value(lvn+1)=0.0d0
1217: ntemp=noncon
1218: noncon=0
1219: if (ntemp.gt.0) go to 150
1220: if (iterno.eq.1) go to 150
1221: do 140 i=2,numnod
1222: vold=value(lvnim1+i)
1223: vnew=value(lvn+i)
1224: tol=reltol*dmax1(dabs(vold),dabs(vnew))+vntol
1225: if (dabs(vold-vnew).le.tol) go to 140
1226: noncon=noncon+1
1227: 140 continue
1228: 150 call copy8(value(lvn+1),value(lvnim1+1),nstop)
1229: go to 10
1230: c
1231: c no convergence
1232: c
1233: 200 igoof=1
1234: 300 if (ndrflo.eq.0) go to 400
1235: write (6,301) ndrflo
1236: 301 format('0warning: underflow occurred ',i4,' time(s)')
1237: c
1238: c finished
1239: c
1240: 400 return
1241: end
1242: subroutine load
1243: implicit double precision (a-h,o-z)
1244: c
1245: c this routine zeroes-out and then loads the coefficient matrix.
1246: c the active devices and the controlled sources are loaded by separate
1247: c subroutines.
1248: c
1249: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1250: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
1251: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
1252: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
1253: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
1254: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
1255: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1256: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
1257: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
1258: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
1259: 2 itemno,nosolv,ipostp,iscrch
1260: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1261: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
1262: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
1263: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
1264: common /blank/ value(1000)
1265: integer nodplc(64)
1266: complex*16 cvalue(32)
1267: equivalence (value(1),nodplc(1),cvalue(1))
1268: c
1269: c
1270: dimension qcap(1),ccap(1)
1271: equivalence (qcap(1),value(1)),(ccap(1),value(2))
1272: dimension find(1),vind(1)
1273: equivalence (find(1),value(1)),(vind(1),value(2))
1274: c
1275: c zero y matrix and current vector
1276: c
1277: call zero8(value(lvn+1),nstop+nstop+nut+nlt)
1278: c
1279: c resistors
1280: c
1281: loc=locate(1)
1282: 20 if (loc.eq.0) go to 30
1283: locv=nodplc(loc+1)
1284: val=value(locv+1)
1285: locy=lynl+nodplc(loc+6)
1286: value(locy)=value(locy)+val
1287: locy=lynl+nodplc(loc+7)
1288: value(locy)=value(locy)+val
1289: locy=lynl+nodplc(loc+4)
1290: value(locy)=value(locy)-val
1291: locy=lynl+nodplc(loc+5)
1292: value(locy)=value(locy)-val
1293: loc=nodplc(loc)
1294: go to 20
1295: c
1296: c capacitors
1297: c
1298: 30 loc=locate(2)
1299: 40 if (loc.eq.0) go to 100
1300: locv=nodplc(loc+1)
1301: node1=nodplc(loc+2)
1302: node2=nodplc(loc+3)
1303: lcoef=nodplc(loc+7)
1304: call sizmem(nodplc(loc+7),ncoef)
1305: loct=nodplc(loc+8)
1306: vcap=value(locv+2)
1307: if ((mode.eq.1).and.(initf.eq.2)) go to 45
1308: if ((nosolv.ne.0).and.(initf.eq.5)) go to 45
1309: vcap=value(lvnim1+node1)-value(lvnim1+node2)
1310: 45 value(locv+3)=vcap
1311: if (mode.eq.1) go to 60
1312: if (initf.ne.6) go to 50
1313: qcap(lx0+loct)=qcap(lx1+loct)
1314: go to 60
1315: 50 call evpoly(qcap(lx0+loct),-1,lcoef,ncoef,locv+2,1,loc+8)
1316: if (initf.ne.5) go to 60
1317: if (nosolv.eq.0) go to 55
1318: vcap=value(locv+2)
1319: value(locv+3)=vcap
1320: call evpoly(qcap(lx0+loct),-1,lcoef,ncoef,locv+2,1,loc+8)
1321: 55 qcap(lx1+loct)=qcap(lx0+loct)
1322: 60 call evpoly(value(locv+1),0,lcoef,ncoef,locv+2,1,loc+8)
1323: if (mode.eq.1) go to 90
1324: call intgr8(geq,ceq,value(locv+1),loct)
1325: ceq=ceq-geq*vcap+ag(1)*qcap(lx0+loct)
1326: if(initf.ne.5) go to 70
1327: ccap(lx1+loct)=ccap(lx0+loct)
1328: 70 locy=lynl+nodplc(loc+10)
1329: value(locy)=value(locy)+geq
1330: locy=lynl+nodplc(loc+11)
1331: value(locy)=value(locy)+geq
1332: locy=lynl+nodplc(loc+5)
1333: value(locy)=value(locy)-geq
1334: locy=lynl+nodplc(loc+6)
1335: value(locy)=value(locy)-geq
1336: value(lvn+node1)=value(lvn+node1)-ceq
1337: value(lvn+node2)=value(lvn+node2)+ceq
1338: 90 loc=nodplc(loc)
1339: go to 40
1340: c
1341: c inductors
1342: c
1343: 100 if (jelcnt(3).eq.0) go to 400
1344: if (mode.eq.1) go to 150
1345: if (initf.eq.6) go to 150
1346: loc=locate(3)
1347: 110 if (loc.eq.0) go to 120
1348: locv=nodplc(loc+1)
1349: iptr=nodplc(loc+5)
1350: lcoef=nodplc(loc+10)
1351: call sizmem(nodplc(loc+10),ncoef)
1352: loct=nodplc(loc+11)
1353: cind=value(lvnim1+iptr)
1354: if ((mode.eq.1).and.(initf.eq.2)) cind=value(locv+2)
1355: if ((initf.eq.5).and.(nosolv.ne.0)) cind=value(locv+2)
1356: value(locv+3)=cind
1357: call evpoly(find(lx0+loct),-1,lcoef,ncoef,locv+2,1,loc+11)
1358: loc=nodplc(loc)
1359: go to 110
1360: 120 loc=locate(4)
1361: 130 if (loc.eq.0) go to 150
1362: locv=nodplc(loc+1)
1363: nl1=nodplc(loc+2)
1364: nl2=nodplc(loc+3)
1365: iptr1=nodplc(nl1+5)
1366: iptr2=nodplc(nl2+5)
1367: loct1=nodplc(nl1+11)
1368: loct2=nodplc(nl2+11)
1369: find(lx0+loct1)=find(lx0+loct1)+value(locv+1)*value(lvnim1+iptr2)
1370: find(lx0+loct2)=find(lx0+loct2)+value(locv+1)*value(lvnim1+iptr1)
1371: loc=nodplc(loc)
1372: go to 130
1373: 150 loc=locate(3)
1374: 160 if (loc.eq.0) go to 300
1375: locv=nodplc(loc+1)
1376: iptr=nodplc(loc+5)
1377: lcoef=nodplc(loc+10)
1378: call sizmem(nodplc(loc+10),ncoef)
1379: loct=nodplc(loc+11)
1380: cind=value(lvnim1+iptr)
1381: if ((mode.eq.1).and.(initf.eq.2)) cind=value(locv+2)
1382: if ((nosolv.ne.0).and.(initf.eq.5)) cind=value(locv+2)
1383: value(locv+3)=cind
1384: if (mode.ne.1) go to 200
1385: veq=0.0d0
1386: req=0.0d0
1387: go to 210
1388: 200 if (initf.ne.6) go to 205
1389: find(lx0+loct)=find(lx1+loct)
1390: go to 210
1391: 205 if (initf.ne.5) go to 210
1392: find(lx1+loct)=find(lx0+loct)
1393: 210 call evpoly(value(locv+1),0,lcoef,ncoef,locv+2,1,loc+11)
1394: if (mode.eq.1) go to 250
1395: call intgr8(req,veq,value(locv+1),loct)
1396: if (ncoef.eq.1) go to 250
1397: veq=veq-req*cind+ag(1)*find(lx0+loct)
1398: 250 value(lvn+iptr)=veq
1399: if(initf.ne.5) go to 260
1400: vind(lx1+loct)=vind(lx0+loct)
1401: 260 locy=lynl+nodplc(loc+13)
1402: value(locy)=-req
1403: locy=lynl+nodplc(loc+6)
1404: value(locy)=1.0d0
1405: locy=lynl+nodplc(loc+7)
1406: value(locy)=-1.0d0
1407: locy=lynl+nodplc(loc+8)
1408: value(locy)=1.0d0
1409: locy=lynl+nodplc(loc+9)
1410: value(locy)=-1.0d0
1411: loc=nodplc(loc)
1412: go to 160
1413: c
1414: c mutual inductances
1415: c
1416: 300 loc=locate(4)
1417: 310 if (loc.eq.0) go to 400
1418: locv=nodplc(loc+1)
1419: req=ag(1)*value(locv+1)
1420: locy=lynl+nodplc(loc+4)
1421: value(locy)=-req
1422: locy=lynl+nodplc(loc+5)
1423: value(locy)=-req
1424: loc=nodplc(loc)
1425: go to 310
1426: c
1427: c nonlinear controlled sources
1428: c
1429: 400 call nlcsrc
1430: c
1431: c voltage sources
1432: c
1433: loc=locate(9)
1434: 610 if (loc.eq.0) go to 700
1435: locv=nodplc(loc+1)
1436: iptr=nodplc(loc+6)
1437: value(lvn+iptr)=value(locv+1)
1438: locy=lynl+nodplc(loc+7)
1439: value(locy)=value(locy)+1.0d0
1440: locy=lynl+nodplc(loc+8)
1441: value(locy)=value(locy)-1.0d0
1442: locy=lynl+nodplc(loc+9)
1443: value(locy)=value(locy)+1.0d0
1444: locy=lynl+nodplc(loc+10)
1445: value(locy)=value(locy)-1.0d0
1446: loc=nodplc(loc)
1447: go to 610
1448: c
1449: c current sources
1450: c
1451: 700 loc=locate(10)
1452: 710 if (loc.eq.0) go to 800
1453: locv=nodplc(loc+1)
1454: node1=nodplc(loc+2)
1455: node2=nodplc(loc+3)
1456: val=value(locv+1)
1457: value(lvn+node1)=value(lvn+node1)-val
1458: value(lvn+node2)=value(lvn+node2)+val
1459: loc=nodplc(loc)
1460: go to 710
1461: c
1462: c call device model routines
1463: c
1464: 800 call diode
1465: call bjt
1466: call jfet
1467: call mosfet
1468: c
1469: c transmission lines
1470: c
1471: loc=locate(17)
1472: 910 if (loc.eq.0) go to 980
1473: locv=nodplc(loc+1)
1474: z0=value(locv+1)
1475: y0=1.0d0/z0
1476: node1=nodplc(loc+2)
1477: node2=nodplc(loc+3)
1478: node3=nodplc(loc+4)
1479: node4=nodplc(loc+5)
1480: ibr1=nodplc(loc+8)
1481: ibr2=nodplc(loc+9)
1482: locy=lynl+nodplc(loc+10)
1483: value(locy)=value(locy)+y0
1484: locy=lynl+nodplc(loc+11)
1485: value(locy)=-y0
1486: locy=lynl+nodplc(loc+12)
1487: value(locy)=-1.0d0
1488: locy=lynl+nodplc(loc+13)
1489: value(locy)=value(locy)+y0
1490: locy=lynl+nodplc(loc+14)
1491: value(locy)=-1.0d0
1492: locy=lynl+nodplc(loc+15)
1493: value(locy)=-y0
1494: locy=lynl+nodplc(loc+16)
1495: value(locy)=+y0
1496: locy=lynl+nodplc(loc+17)
1497: value(locy)=+1.0d0
1498: locy=lynl+nodplc(loc+18)
1499: value(locy)=+y0
1500: locy=lynl+nodplc(loc+19)
1501: value(locy)=+1.0d0
1502: locy=lynl+nodplc(loc+20)
1503: value(locy)=-1.0d0
1504: locy=lynl+nodplc(loc+23)
1505: value(locy)=+1.0d0
1506: locy=lynl+nodplc(loc+27)
1507: value(locy)=-1.0d0
1508: locy=lynl+nodplc(loc+28)
1509: value(locy)=+1.0d0
1510: locy=lynl+nodplc(loc+31)
1511: value(locy)=-y0
1512: locy=lynl+nodplc(loc+32)
1513: value(locy)=-y0
1514: if (mode.ne.1) go to 920
1515: locy=lynl+nodplc(loc+21)
1516: value(locy)=-1.0d0
1517: locy=lynl+nodplc(loc+22)
1518: value(locy)=+1.0d0
1519: locy=lynl+nodplc(loc+24)
1520: value(locy)=-(1.0d0-gmin)*z0
1521: locy=lynl+nodplc(loc+25)
1522: value(locy)=-1.0d0
1523: locy=lynl+nodplc(loc+26)
1524: value(locy)=+1.0d0
1525: locy=lynl+nodplc(loc+29)
1526: value(locy)=-(1.0d0-gmin)*z0
1527: go to 950
1528: 920 if (initf.ne.5) go to 930
1529: if (nosolv.ne.0) go to 925
1530: value(locv+3)=value(lvnim1+node3)-value(lvnim1+node4)
1531: 1 +value(lvnim1+ibr2)*z0
1532: value(locv+4)=value(lvnim1+node1)-value(lvnim1+node2)
1533: 1 +value(lvnim1+ibr1)*z0
1534: go to 930
1535: 925 value(locv+3)=value(locv+7)+value(locv+8)*z0
1536: value(locv+4)=value(locv+5)+value(locv+6)*z0
1537: 930 value(lvn+ibr1)=value(locv+3)
1538: value(lvn+ibr2)=value(locv+4)
1539: 950 loc=nodplc(loc)
1540: go to 910
1541: c
1542: c initialize nodes
1543: c
1544: 980 if(mode.ne.1) go to 995
1545: if(initf.ne.3.and.initf.ne.2) go to 1000
1546: call sizmem(nsnod,nic)
1547: if(nic.eq.0) go to 995
1548: call sizmem(icnod,ntest)
1549: if(modedc.eq.2.and.ntest.ne.0) go to 995
1550: g=1.0d0
1551: do 990 i=1,nic
1552: locy=lynl+nodplc(nsmat+i)
1553: value(locy)=value(locy)+g
1554: node=nodplc(nsnod+i)
1555: value(lvn+node)=value(lvn+node)+value(nsval+i)*g
1556: 990 continue
1557: c
1558: c transient initial conditions (uic not specified)
1559: c
1560: 995 if(mode.ne.1) go to 1000
1561: if(modedc.ne.2) go to 1000
1562: if(nosolv.ne.0) go to 1000
1563: call sizmem(icnod,nic)
1564: if(nic.eq.0) go to 1000
1565: g=1.0d0
1566: do 996 i=1,nic
1567: locy=lynl+nodplc(icmat+i)
1568: value(locy)=value(locy)+g
1569: node=nodplc(icnod+i)
1570: value(lvn+node)=value(lvn+node)+value(icval+i)*g
1571: 996 continue
1572: c
1573: c reorder right-hand side
1574: c
1575: 1000 do 1010 i=2,nstop
1576: j=nodplc(iswap+i)
1577: value(ndiag+i)=value(lvn+j)
1578: 1010 continue
1579: call copy8(value(ndiag+1),value(lvn+1),nstop)
1580: c
1581: c finished
1582: c
1583: return
1584: end
1585: subroutine nlcsrc
1586: implicit double precision (a-h,o-z)
1587: c
1588: c this routine loads the nonlinear controlled sources into the
1589: c coefficient matrix.
1590: c
1591: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1592: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
1593: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
1594: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
1595: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
1596: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
1597: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
1598: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
1599: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
1600: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
1601: 2 itemno,nosolv,ipostp,iscrch
1602: common /flags/ iprnta,iprntl,iprntm,iprntn,iprnto,limtim,limpts,
1603: 1 lvlcod,lvltim,itl1,itl2,itl3,itl4,itl5,igoof,nogo,keof
1604: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
1605: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
1606: common /blank/ value(1000)
1607: integer nodplc(64)
1608: complex*16 cvalue(32)
1609: equivalence (value(1),nodplc(1),cvalue(1))
1610: c
1611: c nonlinear voltage-controlled current sources
1612: c
1613: loc=locate(5)
1614: 10 if (loc.eq.0) go to 100
1615: node1=nodplc(loc+2)
1616: node2=nodplc(loc+3)
1617: ndim=nodplc(loc+4)
1618: lnod=nodplc(loc+6)
1619: lmat=nodplc(loc+7)
1620: lcoef=nodplc(loc+8)
1621: call sizmem(nodplc(loc+8),ncoef)
1622: larg=nodplc(loc+9)
1623: lexp=nodplc(loc+10)
1624: lic=nodplc(loc+11)
1625: loct=nodplc(loc+12)+1
1626: icheck=0
1627: do 20 i=1,ndim
1628: call update(value(lic+i),loct,nodplc(lnod+1),nodplc(lnod+2),2,
1629: 1 icheck)
1630: value(larg+i)=value(lx0+loct)
1631: loct=loct+2
1632: lnod=lnod+2
1633: 20 continue
1634: call evpoly(cold,0,lcoef,ncoef,larg,ndim,lexp)
1635: loct=nodplc(loc+12)
1636: if (icheck.eq.1) go to 30
1637: if (initf.eq.6) go to 30
1638: tol=reltol*dmax1(dabs(cold),dabs(value(lx0+loct)))+abstol
1639: if (dabs(cold-value(lx0+loct)).lt.tol) go to 40
1640: 30 noncon=noncon+1
1641: 40 value(lx0+loct)=cold
1642: ceq=cold
1643: do 50 i=1,ndim
1644: call evpoly(geq,i,lcoef,ncoef,larg,ndim,lexp)
1645: loct=loct+2
1646: value(lx0+loct)=geq
1647: ceq=ceq-geq*value(larg+i)
1648: locy=lynl+nodplc(lmat+1)
1649: value(locy)=value(locy)+geq
1650: locy=lynl+nodplc(lmat+2)
1651: value(locy)=value(locy)-geq
1652: locy=lynl+nodplc(lmat+3)
1653: value(locy)=value(locy)-geq
1654: locy=lynl+nodplc(lmat+4)
1655: value(locy)=value(locy)+geq
1656: lmat=lmat+4
1657: 50 continue
1658: value(lvn+node1)=value(lvn+node1)-ceq
1659: value(lvn+node2)=value(lvn+node2)+ceq
1660: loc=nodplc(loc)
1661: go to 10
1662: c
1663: c nonlinear voltage controlled voltage sources
1664: c
1665: 100 loc=locate(6)
1666: 110 if (loc.eq.0) go to 200
1667: node1=nodplc(loc+2)
1668: node2=nodplc(loc+3)
1669: ndim=nodplc(loc+4)
1670: iptr=nodplc(loc+6)
1671: lnod=nodplc(loc+7)
1672: lmat=nodplc(loc+8)
1673: lcoef=nodplc(loc+9)
1674: call sizmem(nodplc(loc+9),ncoef)
1675: larg=nodplc(loc+10)
1676: lexp=nodplc(loc+11)
1677: lic=nodplc(loc+12)
1678: loct=nodplc(loc+13)+2
1679: icheck=0
1680: do 120 i=1,ndim
1681: call update(value(lic+i),loct,nodplc(lnod+1),nodplc(lnod+2),2,
1682: 1 icheck)
1683: value(larg+i)=value(lx0+loct)
1684: loct=loct+2
1685: lnod=lnod+2
1686: 120 continue
1687: call evpoly(volt,0,lcoef,ncoef,larg,ndim,lexp)
1688: loct=nodplc(loc+13)
1689: if (icheck.eq.1) go to 130
1690: if (initf.eq.6) go to 130
1691: tol=reltol*dmax1(dabs(volt),dabs(value(lx0+loct)))+vntol
1692: if (dabs(volt-value(lx0+loct)).lt.tol) go to 140
1693: 130 noncon=noncon+1
1694: 140 value(lx0+loct)=volt
1695: value(lx0+loct+1)=value(lvnim1+iptr)
1696: veq=volt
1697: locy=lynl+nodplc(lmat+1)
1698: value(locy)=+1.0d0
1699: locy=lynl+nodplc(lmat+2)
1700: value(locy)=-1.0d0
1701: locy=lynl+nodplc(lmat+3)
1702: value(locy)=+1.0d0
1703: locy=lynl+nodplc(lmat+4)
1704: value(locy)=-1.0d0
1705: lmat=lmat+4
1706: loct=loct+1
1707: do 150 i=1,ndim
1708: call evpoly(vgain,i,lcoef,ncoef,larg,ndim,lexp)
1709: loct=loct+2
1710: value(lx0+loct)=vgain
1711: veq=veq-vgain*value(larg+i)
1712: locy=lynl+nodplc(lmat+1)
1713: value(locy)=value(locy)-vgain
1714: locy=lynl+nodplc(lmat+2)
1715: value(locy)=value(locy)+vgain
1716: lmat=lmat+2
1717: 150 continue
1718: value(lvn+iptr)=veq
1719: loc=nodplc(loc)
1720: go to 110
1721: c
1722: c nonlinear current-controlled current sources
1723: c
1724: 200 loc=locate(7)
1725: 210 if (loc.eq.0) go to 300
1726: node1=nodplc(loc+2)
1727: node2=nodplc(loc+3)
1728: ndim=nodplc(loc+4)
1729: lvs=nodplc(loc+6)
1730: lmat=nodplc(loc+7)
1731: lcoef=nodplc(loc+8)
1732: call sizmem(nodplc(loc+8),ncoef)
1733: larg=nodplc(loc+9)
1734: lexp=nodplc(loc+10)
1735: lic=nodplc(loc+11)
1736: loct=nodplc(loc+12)+1
1737: icheck=0
1738: do 220 i=1,ndim
1739: iptr=nodplc(lvs+i)
1740: iptr=nodplc(iptr+6)
1741: call update(value(lic+i),loct,iptr,1,2,icheck)
1742: value(larg+i)=value(lx0+loct)
1743: loct=loct+2
1744: 220 continue
1745: call evpoly(csrc,0,lcoef,ncoef,larg,ndim,lexp)
1746: loct=nodplc(loc+12)
1747: if (icheck.eq.1) go to 230
1748: if (initf.eq.6) go to 230
1749: tol=reltol*dmax1(dabs(csrc),dabs(value(lx0+loct)))+abstol
1750: if (dabs(csrc-value(lx0+loct)).lt.tol) go to 240
1751: 230 noncon=noncon+1
1752: 240 value(lx0+loct)=csrc
1753: ceq=csrc
1754: do 250 i=1,ndim
1755: call evpoly(cgain,i,lcoef,ncoef,larg,ndim,lexp)
1756: loct=loct+2
1757: value(lx0+loct)=cgain
1758: ceq=ceq-cgain*value(larg+i)
1759: locy=lynl+nodplc(lmat+1)
1760: value(locy)=value(locy)+cgain
1761: locy=lynl+nodplc(lmat+2)
1762: value(locy)=value(locy)-cgain
1763: lmat=lmat+2
1764: 250 continue
1765: value(lvn+node1)=value(lvn+node1)-ceq
1766: value(lvn+node2)=value(lvn+node2)+ceq
1767: loc=nodplc(loc)
1768: go to 210
1769: c
1770: c nonlinear current controlled voltage sources
1771: c
1772: 300 loc=locate(8)
1773: 310 if (loc.eq.0) go to 1000
1774: node1=nodplc(loc+2)
1775: node2=nodplc(loc+3)
1776: ndim=nodplc(loc+4)
1777: ibr=nodplc(loc+6)
1778: lvs=nodplc(loc+7)
1779: lmat=nodplc(loc+8)
1780: lcoef=nodplc(loc+9)
1781: call sizmem(nodplc(loc+9),ncoef)
1782: larg=nodplc(loc+10)
1783: lexp=nodplc(loc+11)
1784: lic=nodplc(loc+12)
1785: loct=nodplc(loc+13)+2
1786: icheck=0
1787: do 320 i=1,ndim
1788: iptr=nodplc(lvs+i)
1789: iptr=nodplc(iptr+6)
1790: call update(value(lic+i),loct,iptr,1,2,icheck)
1791: value(larg+i)=value(lx0+loct)
1792: loct=loct+2
1793: 320 continue
1794: call evpoly(volt,0,lcoef,ncoef,larg,ndim,lexp)
1795: loct=nodplc(loc+13)
1796: if (icheck.eq.1) go to 330
1797: if (initf.eq.6) go to 330
1798: tol=reltol*dmax1(dabs(volt),dabs(value(lx0+loct)))+vntol
1799: if (dabs(volt-value(lx0+loct)).lt.tol) go to 340
1800: 330 noncon=noncon+1
1801: 340 value(lx0+loct)=volt
1802: value(lx0+loct+1)=value(lvnim1+ibr)
1803: veq=volt
1804: locy=lynl+nodplc(lmat+1)
1805: value(locy)=+1.0d0
1806: locy=lynl+nodplc(lmat+2)
1807: value(locy)=-1.0d0
1808: locy=lynl+nodplc(lmat+3)
1809: value(locy)=+1.0d0
1810: locy=lynl+nodplc(lmat+4)
1811: value(locy)=-1.0d0
1812: lmat=lmat+4
1813: loct=loct+1
1814: do 350 i=1,ndim
1815: call evpoly(transr,i,lcoef,ncoef,larg,ndim,lexp)
1816: loct=loct+2
1817: value(lx0+loct)=transr
1818: veq=veq-transr*value(larg+i)
1819: locy=lynl+nodplc(lmat+i)
1820: value(locy)=value(locy)-transr
1821: 350 continue
1822: value(lvn+ibr)=veq
1823: loc=nodplc(loc)
1824: go to 310
1825: c
1826: c finished
1827: c
1828: 1000 return
1829: end
1830: subroutine update(vinit,loct,node1,node2,nupda,icheck)
1831: implicit double precision (a-h,o-z)
1832: c
1833: c this routine updates and limits the controlling variables for the
1834: c nonlinear controlled sources.
1835: c
1836: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
1837: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
1838: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
1839: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
1840: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
1841: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
1842: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
1843: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
1844: 2 itemno,nosolv,ipostp,iscrch
1845: common /blank/ value(1000)
1846: integer nodplc(64)
1847: complex*16 cvalue(32)
1848: equivalence (value(1),nodplc(1),cvalue(1))
1849: c
1850: c
1851: go to (40,10,40,20,30,50), initf
1852: 10 vnew=vinit
1853: go to 70
1854: 20 vnew=value(lx0+loct)
1855: go to 70
1856: 30 vnew=value(lx1+loct)
1857: go to 70
1858: 40 vnew=value(lvnim1+node1)-value(lvnim1+node2)
1859: go to 60
1860: 50 call copy8(value(lx1+loct),value(lx0+loct),nupda)
1861: xfact=delta/delold(2)
1862: vnew=(1.0d0+xfact)*value(lx1+loct)-xfact*value(lx2+loct)
1863: 60 if (dabs(vnew).le.1.0d0) go to 80
1864: delv=vnew-value(lx0+loct)
1865: if (dabs(delv).le.0.1d0) go to 80
1866: vlim=dmax1(dabs(0.1d0*value(lx0+loct)),0.1d0)
1867: vnew=value(lx0+loct)+dsign(dmin1(dabs(delv),vlim),delv)
1868: go to 70
1869: 70 icheck=1
1870: 80 value(lx0+loct)=vnew
1871: return
1872: end
1873: subroutine evpoly(result,itype,lcoef,ncoef,larg,
1874: 1 narg,lexp)
1875: implicit double precision (a-h,o-z)
1876: c
1877: c this routine evaluates a polynomial. lcoef points to the coef-
1878: c ficients, and larg points to the values of the polynomial argument(s).
1879: c
1880: common /blank/ value(1000)
1881: integer nodplc(64)
1882: complex*16 cvalue(32)
1883: equivalence (value(1),nodplc(1),cvalue(1))
1884: c
1885: c
1886: if (itype) 100,200,300
1887: c
1888: c integration (polynomial *must* be one-dimensional)
1889: c
1890: 100 result=0.0d0
1891: arg=1.0d0
1892: arg1=value(larg+1)
1893: do 110 i=1,ncoef
1894: arg=arg*arg1
1895: result=result+value(lcoef+i)*arg/dfloat(i)
1896: 110 continue
1897: go to 1000
1898: c
1899: c evaluation of the polynomial
1900: c
1901: 200 result=value(lcoef+1)
1902: if (ncoef.eq.1) go to 1000
1903: call zero4(nodplc(lexp+1),narg)
1904: do 220 i=2,ncoef
1905: call nxtpwr(nodplc(lexp+1),narg)
1906: if (value(lcoef+i).eq.0.0d0) go to 220
1907: arg=1.0d0
1908: do 210 j=1,narg
1909: call evterm(val,value(larg+j),nodplc(lexp+j))
1910: arg=arg*val
1911: 210 continue
1912: result=result+value(lcoef+i)*arg
1913: 220 continue
1914: go to 1000
1915: c
1916: c partial derivative with respect to the itype*th variable
1917: c
1918: 300 result=0.0d0
1919: if (ncoef.eq.1) go to 1000
1920: call zero4(nodplc(lexp+1),narg)
1921: do 330 i=2,ncoef
1922: call nxtpwr(nodplc(lexp+1),narg)
1923: if (nodplc(lexp+itype).eq.0) go to 330
1924: if (value(lcoef+i).eq.0.0d0) go to 330
1925: arg=1.0d0
1926: do 320 j=1,narg
1927: if (j.eq.itype) go to 310
1928: call evterm(val,value(larg+j),nodplc(lexp+j))
1929: arg=arg*val
1930: go to 320
1931: 310 call evterm(val,value(larg+j),nodplc(lexp+j)-1)
1932: arg=arg*dfloat(nodplc(lexp+j))*val
1933: 320 continue
1934: result=result+value(lcoef+i)*arg
1935: 330 continue
1936: c
1937: c finished
1938: c
1939: 1000 return
1940: end
1941: subroutine evterm(val,arg,iexp)
1942: implicit double precision (a-h,o-z)
1943: c
1944: c this routine evaluates one term of a polynomial.
1945: c
1946: jexp=iexp+1
1947: if (jexp.ge.6) go to 60
1948: go to (10,20,30,40,50), jexp
1949: 10 val=1.0d0
1950: go to 100
1951: 20 val=arg
1952: go to 100
1953: 30 val=arg*arg
1954: go to 100
1955: 40 val=arg*arg*arg
1956: go to 100
1957: 50 val=arg*arg
1958: val=val*val
1959: go to 100
1960: 60 if (arg.eq.0.0d0) go to 70
1961: argexp=dfloat(iexp)*dlog(dabs(arg))
1962: if (argexp.lt.-200.0d0) go to 70
1963: val=dexp(argexp)
1964: if((iexp/2)*2.eq.iexp) go to 100
1965: val=dsign(val,arg)
1966: go to 100
1967: 70 val=0.0d0
1968: c
1969: c finished
1970: c
1971: 100 return
1972: end
1973: subroutine nxtpwr(pwrseq,pdim)
1974: implicit double precision (a-h,o-z)
1975: c
1976: c this routine determines the 'next' set of exponents for the
1977: c different dimensions of a polynomial.
1978: c
1979: integer pwrseq(1),pdim,psum
1980: c
1981: c
1982: if (pdim.eq.1) go to 80
1983: k=pdim
1984: 10 if (pwrseq(k).ne.0) go to 20
1985: k=k-1
1986: if (k.ne.0) go to 10
1987: go to 80
1988: 20 if (k.eq.pdim) go to 30
1989: pwrseq(k)=pwrseq(k)-1
1990: pwrseq(k+1)=pwrseq(k+1)+1
1991: go to 100
1992: 30 km1=k-1
1993: do 40 i=1,km1
1994: if (pwrseq(i).ne.0) go to 50
1995: 40 continue
1996: pwrseq(1)=pwrseq(pdim)+1
1997: pwrseq(pdim)=0
1998: go to 100
1999: 50 psum=1
2000: k=pdim
2001: 60 if (pwrseq(k-1).ge.1) go to 70
2002: psum=psum+pwrseq(k)
2003: pwrseq(k)=0
2004: k=k-1
2005: go to 60
2006: 70 pwrseq(k)=pwrseq(k)+psum
2007: pwrseq(k-1)=pwrseq(k-1)-1
2008: go to 100
2009: 80 pwrseq(1)=pwrseq(1)+1
2010: c
2011: c finished
2012: c
2013: 100 return
2014: end
2015: subroutine intgr8(geq,ceq,capval,loct)
2016: implicit double precision (a-h,o-z)
2017: c
2018: c this routine performs the actual numerical integration for each
2019: c circuit element.
2020: c
2021: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
2022: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2023: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
2024: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
2025: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
2026: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
2027: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
2028: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
2029: 2 itemno,nosolv,ipostp,iscrch
2030: common /blank/ value(1000)
2031: integer nodplc(64)
2032: complex*16 cvalue(32)
2033: equivalence (value(1),nodplc(1),cvalue(1))
2034: c
2035: c
2036: dimension qcap(1),ccap(1)
2037: equivalence (qcap(1),value(1)),(ccap(1),value(2))
2038: c
2039: c
2040: if (method.eq.2) go to 100
2041: c
2042: c trapezoidal algorithm
2043: c
2044: if (iord.eq.1) go to 100
2045: ccap(lx0+loct)=-ccap(lx1+loct)*ag(2)
2046: 1 +ag(1)*(qcap(lx0+loct)-qcap(lx1+loct))
2047: go to 190
2048: c
2049: c gears algorithm
2050: c
2051: 100 go to (110,120,130,140,150,160), iord
2052: 110 ccap(lx0+loct)=ag(1)*qcap(lx0+loct)+ag(2)*qcap(lx1+loct)
2053: go to 190
2054: 120 ccap(lx0+loct)=ag(1)*qcap(lx0+loct)+ag(2)*qcap(lx1+loct)
2055: 1 +ag(3)*qcap(lx2+loct)
2056: go to 190
2057: 130 ccap(lx0+loct)=ag(1)*qcap(lx0+loct)+ag(2)*qcap(lx1+loct)
2058: 1 +ag(3)*qcap(lx2+loct)+ag(4)*qcap(lx3+loct)
2059: go to 190
2060: 140 ccap(lx0+loct)=ag(1)*qcap(lx0+loct)+ag(2)*qcap(lx1+loct)
2061: 1 +ag(3)*qcap(lx2+loct)+ag(4)*qcap(lx3+loct)
2062: 2 +ag(5)*qcap(lx4+loct)
2063: go to 190
2064: 150 ccap(lx0+loct)=ag(1)*qcap(lx0+loct)+ag(2)*qcap(lx1+loct)
2065: 1 +ag(3)*qcap(lx2+loct)+ag(4)*qcap(lx3+loct)
2066: 2 +ag(5)*qcap(lx4+loct)+ag(6)*qcap(lx5+loct)
2067: go to 190
2068: 160 ccap(lx0+loct)=ag(1)*qcap(lx0+loct)+ag(2)*qcap(lx1+loct)
2069: 1 +ag(3)*qcap(lx2+loct)+ag(4)*qcap(lx3+loct)
2070: 2 +ag(5)*qcap(lx4+loct)+ag(6)*qcap(lx5+loct)
2071: 3 +ag(7)*qcap(lx6+loct)
2072: c... ceq is the equivalent current applicable to linear capacitance
2073: c (inductance) only, i.e. q=c*v
2074: 190 ceq=ccap(lx0+loct)-ag(1)*qcap(lx0+loct)
2075: geq=ag(1)*capval
2076: return
2077: end
2078: subroutine pnjlim(vnew,vold,vt,vcrit,icheck)
2079: implicit double precision (a-h,o-z)
2080: c
2081: c this routine limits the change-per-iteration of device pn-junction
2082: c voltages.
2083: c
2084: if (vnew.le.vcrit) go to 30
2085: vlim=vt+vt
2086: delv=vnew-vold
2087: if (dabs(delv).le.vlim) go to 30
2088: if (vold.le.0.0d0) go to 20
2089: arg=1.0d0+delv/vt
2090: if (arg.le.0.0d0) go to 10
2091: vnew=vold+vt*dlog(arg)
2092: icheck=1
2093: go to 100
2094: 10 vnew=vcrit
2095: icheck=1
2096: go to 100
2097: 20 vnew=vt*dlog(vnew/vt)
2098: icheck=1
2099: go to 100
2100: 30 continue
2101: c
2102: c finished
2103: c
2104: 100 return
2105: end
2106: subroutine diode
2107: implicit double precision (a-h,o-z)
2108: c
2109: c this routine processes diodes for dc and transient analyses.
2110: c
2111: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
2112: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2113: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
2114: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
2115: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
2116: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
2117: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
2118: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
2119: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
2120: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
2121: 2 itemno,nosolv,ipostp,iscrch
2122: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
2123: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
2124: common /blank/ value(1000)
2125: integer nodplc(64)
2126: complex*16 cvalue(32)
2127: equivalence (value(1),nodplc(1),cvalue(1))
2128: c
2129: c
2130: dimension vdo(1),cdo(1),gdo(1),qd(1),cqd(1)
2131: equivalence (vdo(1),value(1)),(cdo(1),value(2)),
2132: 1 (gdo(1),value(3)),(qd(1),value(4)),(cqd(1),value(5))
2133: c
2134: c
2135: loc=locate(11)
2136: 10 if (loc.eq.0) return
2137: locv=nodplc(loc+1)
2138: node1=nodplc(loc+2)
2139: node2=nodplc(loc+3)
2140: node3=nodplc(loc+4)
2141: locm=nodplc(loc+5)
2142: ioff=nodplc(loc+6)
2143: locm=nodplc(locm+1)
2144: loct=nodplc(loc+11)
2145: c
2146: c dc model parameters
2147: c
2148: area=value(locv+1)
2149: csat=value(locm+1)*area
2150: gspr=value(locm+2)*area
2151: vte=value(locm+3)*vt
2152: bv=value(locm+13)
2153: vcrit=value(locm+18)
2154: c
2155: c initialization
2156: c
2157: icheck=1
2158: go to (100,20,30,50,60,70),initf
2159: 20 if(mode.ne.1.or.modedc.ne.2.or.nosolv.eq.0) go to 25
2160: vd=value(locv+2)
2161: go to 300
2162: 25 if(ioff.ne.0) go to 40
2163: vd=vcrit
2164: go to 300
2165: 30 if (ioff.eq.0) go to 100
2166: 40 vd=0.0d0
2167: go to 300
2168: 50 vd=vdo(lx0+loct)
2169: go to 300
2170: 60 vd=vdo(lx1+loct)
2171: go to 300
2172: 70 xfact=delta/delold(2)
2173: vdo(lx0+loct)=vdo(lx1+loct)
2174: vd=(1.0d0+xfact)*vdo(lx1+loct)-xfact*vdo(lx2+loct)
2175: cdo(lx0+loct)=cdo(lx1+loct)
2176: gdo(lx0+loct)=gdo(lx1+loct)
2177: go to 110
2178: c
2179: c compute new nonlinear branch voltage
2180: c
2181: 100 vd=value(lvnim1+node3)-value(lvnim1+node2)
2182: 110 delvd=vd-vdo(lx0+loct)
2183: cdhat=cdo(lx0+loct)+gdo(lx0+loct)*delvd
2184: c
2185: c bypass if solution has not changed
2186: c
2187: if (6 .eq.6) go to 200
2188: tol=reltol*dmax1(dabs(vd),dabs(vdo(lx0+loct)))+vntol
2189: if (dabs(delvd).ge.tol) go to 200
2190: tol=reltol*dmax1(dabs(cdhat),dabs(cdo(lx0+loct)))+abstol
2191: if (dabs(cdhat-cdo(lx0+loct)).ge.tol) go to 200
2192: vd=vdo(lx0+loct)
2193: cd=cdo(lx0+loct)
2194: gd=gdo(lx0+loct)
2195: go to 800
2196: c
2197: c limit new junction voltage
2198: c
2199: 200 vlim=vte+vte
2200: if(bv.eq.0.0d0) go to 205
2201: if (vd.lt.dmin1(0.0d0,-bv+10.0d0*vte)) go to 210
2202: 205 icheck=0
2203: call pnjlim(vd,vdo(lx0+loct),vte,vcrit,icheck)
2204: go to 300
2205: 210 vdtemp=-(vd+bv)
2206: call pnjlim(vdtemp,-(vdo(lx0+loct)+bv),vte,vcrit,icheck)
2207: vd=-(vdtemp+bv)
2208: c
2209: c compute dc current and derivitives
2210: c
2211: 300 if (vd.lt.-5.0d0*vte) go to 310
2212: evd=dexp(vd/vte)
2213: cd=csat*(evd-1.0d0)+gmin*vd
2214: gd=csat*evd/vte+gmin
2215: go to 330
2216: 310 if(bv.eq.0.0d0) go to 315
2217: if(vd.lt.-bv) go to 320
2218: 315 gd=-csat/vd+gmin
2219: cd=gd*vd
2220: go to 330
2221: 320 evrev=dexp(-(bv+vd)/vt)
2222: cd=-csat*(evrev-1.0d0+bv/vt)
2223: gd=csat*evrev/vt
2224: 330 if (mode.ne.1) go to 500
2225: if ((modedc.eq.2).and.(nosolv.ne.0)) go to 500
2226: if (initf.eq.4) go to 500
2227: go to 700
2228: c
2229: c charge storage elements
2230: c
2231: 500 tau=value(locm+4)
2232: czero=value(locm+5)*area
2233: pb=value(locm+6)
2234: xm=value(locm+7)
2235: fcpb=value(locm+12)
2236: if (vd.ge.fcpb) go to 510
2237: arg=1.0d0-vd/pb
2238: sarg=dexp(-xm*dlog(arg))
2239: qd(lx0+loct)=tau*cd+pb*czero*(1.0d0-arg*sarg)/(1.0d0-xm)
2240: capd=tau*gd+czero*sarg
2241: go to 520
2242: 510 f1=value(locm+15)
2243: f2=value(locm+16)
2244: f3=value(locm+17)
2245: czof2=czero/f2
2246: qd(lx0+loct)=tau*cd+czero*f1+czof2*(f3*(vd-fcpb)
2247: 1 +(xm/(pb+pb))*(vd*vd-fcpb*fcpb))
2248: capd=tau*gd+czof2*(f3+xm*vd/pb)
2249: c
2250: c store small-signal parameters
2251: c
2252: 520 if ((mode.eq.1).and.(modedc.eq.2).and.(nosolv.ne.0)) go to 700
2253: if (initf.ne.4) go to 600
2254: value(lx0+loct+4)=capd
2255: go to 1000
2256: c
2257: c transient analysis
2258: c
2259: 600 if (initf.ne.5) go to 610
2260: qd(lx1+loct)=qd(lx0+loct)
2261: 610 call intgr8(geq,ceq,capd,loct+3)
2262: gd=gd+geq
2263: cd=cd+cqd(lx0+loct)
2264: if (initf.ne.5) go to 700
2265: cqd(lx1+loct)=cqd(lx0+loct)
2266: c
2267: c check convergence
2268: c
2269: 700 if (initf.ne.3) go to 710
2270: if (ioff.eq.0) go to 710
2271: go to 750
2272: 710 if (icheck.eq.1) go to 720
2273: tol=reltol*dmax1(dabs(cdhat),dabs(cd))+abstol
2274: if (dabs(cdhat-cd).le.tol) go to 750
2275: 720 noncon=noncon+1
2276: 750 vdo(lx0+loct)=vd
2277: cdo(lx0+loct)=cd
2278: gdo(lx0+loct)=gd
2279: c
2280: c load current vector
2281: c
2282: 800 cdeq=cd-gd*vd
2283: value(lvn+node2)=value(lvn+node2)+cdeq
2284: value(lvn+node3)=value(lvn+node3)-cdeq
2285: c
2286: c load matrix
2287: c
2288: locy=lynl+nodplc(loc+13)
2289: value(locy)=value(locy)+gspr
2290: locy=lynl+nodplc(loc+14)
2291: value(locy)=value(locy)+gd
2292: locy=lynl+nodplc(loc+15)
2293: value(locy)=value(locy)+gd+gspr
2294: locy=lynl+nodplc(loc+7)
2295: value(locy)=value(locy)-gspr
2296: locy=lynl+nodplc(loc+8)
2297: value(locy)=value(locy)-gd
2298: locy=lynl+nodplc(loc+9)
2299: value(locy)=value(locy)-gspr
2300: locy=lynl+nodplc(loc+10)
2301: value(locy)=value(locy)-gd
2302: 1000 loc=nodplc(loc)
2303: go to 10
2304: end
2305: subroutine bjt
2306: implicit double precision (a-h,o-z)
2307: c
2308: c this routine processes bjts for dc and transient analyses.
2309: c
2310: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
2311: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2312: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
2313: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
2314: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
2315: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
2316: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
2317: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
2318: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
2319: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
2320: 2 itemno,nosolv,ipostp,iscrch
2321: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
2322: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
2323: common /blank/ value(1000)
2324: integer nodplc(64)
2325: complex*16 cvalue(32)
2326: equivalence (value(1),nodplc(1),cvalue(1))
2327: c
2328: c
2329: dimension vbeo(1),vbco(1),cco(1),cbo(1),gpio(1),gmuo(1),gmo(1),
2330: 1 goo(1),qbe(1),cqbe(1),qbc(1),cqbc(1),qcs(1),cqcs(1),qbx(1),
2331: 2 cqbx(1),gxo(1),cexbc(1)
2332: equivalence (vbeo(1),value(1)),(vbco(1),value(2)),
2333: 1 (cco(1),value(3)),(cbo(1),value(4)),(gpio(1),value(5)),
2334: 2 (gmuo(1),value(6)),(gmo(1),value(7)),(goo(1),value(8)),
2335: 3 (qbe(1),value(9)),(cqbe(1),value(10)),(qbc(1),value(11)),
2336: 4 (cqbc(1),value(12)),(qcs(1),value(13)),(cqcs(1),value(14)),
2337: 5 (qbx(1),value(15)),(cqbx(1),value(16)),(gxo(1),value(17)),
2338: 6 (cexbc(1),value(18))
2339: c
2340: c
2341: loc=locate(12)
2342: 10 if (loc.eq.0) return
2343: locv=nodplc(loc+1)
2344: node1=nodplc(loc+2)
2345: node2=nodplc(loc+3)
2346: node3=nodplc(loc+4)
2347: node4=nodplc(loc+5)
2348: node5=nodplc(loc+6)
2349: node6=nodplc(loc+7)
2350: node7=nodplc(loc+30)
2351: locm=nodplc(loc+8)
2352: ioff=nodplc(loc+9)
2353: type=nodplc(locm+2)
2354: locm=nodplc(locm+1)
2355: loct=nodplc(loc+22)
2356: gccs=0.0d0
2357: ceqcs=0.0d0
2358: geqbx=0.0d0
2359: ceqbx=0.0d0
2360: geqcb=0.0d0
2361: c
2362: c dc model paramters
2363: c
2364: area=value(locv+1)
2365: bfm=value(locm+2)
2366: brm=value(locm+8)
2367: csat=value(locm+1)*area
2368: rbpr=value(locm+18)/area
2369: rbpi=value(locm+16)/area-rbpr
2370: gcpr=value(locm+20)*area
2371: gepr=value(locm+19)*area
2372: ova=value(locm+4)
2373: ovb=value(locm+10)
2374: oik=value(locm+5)/area
2375: c2=value(locm+6)*area
2376: vte=value(locm+7)*vt
2377: oikr=value(locm+11)/area
2378: c4=value(locm+12)*area
2379: vtc=value(locm+13)*vt
2380: vcrit=value(locm+54)
2381: td=value(locm+28)
2382: xjrb=value(locm+17)*area
2383: c
2384: c initialization
2385: c
2386: icheck=1
2387: go to (100,20,30,50,60,70),initf
2388: 20 if(mode.ne.1.or.modedc.ne.2.or.nosolv.eq.0) go to 25
2389: vbe=type*value(locv+2)
2390: vce=type*value(locv+3)
2391: vbc=vbe-vce
2392: vbx=vbc
2393: vcs=0.0d0
2394: go to 300
2395: 25 if(ioff.ne.0) go to 40
2396: vbe=vcrit
2397: vbc=0.0d0
2398: go to 300
2399: 30 if (ioff.eq.0) go to 100
2400: 40 vbe=0.0d0
2401: vbc=0.0d0
2402: go to 300
2403: 50 vbe=vbeo(lx0+loct)
2404: vbc=vbco(lx0+loct)
2405: vbx=type*(value(lvnim1+node2)-value(lvnim1+node4))
2406: vcs=type*(value(lvnim1+node7)-value(lvnim1+node4))
2407: go to 300
2408: 60 vbe=vbeo(lx1+loct)
2409: vbc=vbco(lx1+loct)
2410: vbx=type*(value(lvnim1+node2)-value(lvnim1+node4))
2411: vcs=type*(value(lvnim1+node7)-value(lvnim1+node4))
2412: if(mode.ne.2.or.nosolv.eq.0) go to 300
2413: vbx=type*(value(locv+2)-value(locv+3))
2414: vcs=0.0d0
2415: go to 300
2416: 70 xfact=delta/delold(2)
2417: vbeo(lx0+loct)=vbeo(lx1+loct)
2418: vbe=(1.0d0+xfact)*vbeo(lx1+loct)-xfact*vbeo(lx2+loct)
2419: vbco(lx0+loct)=vbco(lx1+loct)
2420: vbc=(1.0d0+xfact)*vbco(lx1+loct)-xfact*vbco(lx2+loct)
2421: cco(lx0+loct)=cco(lx1+loct)
2422: cbo(lx0+loct)=cbo(lx1+loct)
2423: gpio(lx0+loct)=gpio(lx1+loct)
2424: gmuo(lx0+loct)=gmuo(lx1+loct)
2425: gmo(lx0+loct)=gmo(lx1+loct)
2426: goo(lx0+loct)=goo(lx1+loct)
2427: go to 110
2428: c
2429: c compute new nonlinear branch voltages
2430: c
2431: 100 vbe=type*(value(lvnim1+node5)-value(lvnim1+node6))
2432: vbc=type*(value(lvnim1+node5)-value(lvnim1+node4))
2433: 110 delvbe=vbe-vbeo(lx0+loct)
2434: delvbc=vbc-vbco(lx0+loct)
2435: vbx=type*(value(lvnim1+node2)-value(lvnim1+node4))
2436: vcs=type*(value(lvnim1+node7)-value(lvnim1+node4))
2437: cchat=cco(lx0+loct)+(gmo(lx0+loct)+goo(lx0+loct))*delvbe
2438: 1 -(goo(lx0+loct)+gmuo(lx0+loct))*delvbc
2439: cbhat=cbo(lx0+loct)+gpio(lx0+loct)*delvbe+gmuo(lx0+loct)*delvbc
2440: c
2441: c limit nonlinear branch voltages
2442: c
2443: 200 icheck=0
2444: call pnjlim(vbe,vbeo(lx0+loct),vt,vcrit,icheck)
2445: call pnjlim(vbc,vbco(lx0+loct),vt,vcrit,icheck)
2446: c
2447: c determine dc current and derivitives
2448: c
2449: 300 vtn=vt*value(locm+3)
2450: if(vbe.le.-5.0d0*vtn) go to 320
2451: evbe=dexp(vbe/vtn)
2452: cbe=csat*(evbe-1.0d0)+gmin*vbe
2453: gbe=csat*evbe/vtn+gmin
2454: if (c2.ne.0.0d0) go to 310
2455: cben=0.0d0
2456: gben=0.0d0
2457: go to 350
2458: 310 evben=dexp(vbe/vte)
2459: cben=c2*(evben-1.0d0)
2460: gben=c2*evben/vte
2461: go to 350
2462: 320 gbe=-csat/vbe+gmin
2463: cbe=gbe*vbe
2464: gben=-c2/vbe
2465: cben=gben*vbe
2466: 350 vtn=vt*value(locm+9)
2467: if(vbc.le.-5.0d0*vtn) go to 370
2468: evbc=dexp(vbc/vtn)
2469: cbc=csat*(evbc-1.0d0)+gmin*vbc
2470: gbc=csat*evbc/vtn+gmin
2471: if (c4.ne.0.0d0) go to 360
2472: cbcn=0.0d0
2473: gbcn=0.0d0
2474: go to 400
2475: 360 evbcn=dexp(vbc/vtc)
2476: cbcn=c4*(evbcn-1.0d0)
2477: gbcn=c4*evbcn/vtc
2478: go to 400
2479: 370 gbc=-csat/vbc+gmin
2480: cbc=gbc*vbc
2481: gbcn=-c4/vbc
2482: cbcn=gbcn*vbc
2483: c
2484: c determine base charge terms
2485: c
2486: 400 q1=1.0d0/(1.0d0-ova*vbc-ovb*vbe)
2487: if (oik.ne.0.0d0) go to 405
2488: if (oikr.ne.0.0d0) go to 405
2489: qb=q1
2490: dqbdve=q1*qb*ovb
2491: dqbdvc=q1*qb*ova
2492: go to 410
2493: 405 q2=oik*cbe+oikr*cbc
2494: arg=dmax1(0.0d0,1.0d0+4.0d0*q2)
2495: sqarg=1.0d0
2496: if(arg.ne.0.0d0) sqarg=dsqrt(arg)
2497: qb=q1*(1.0d0+sqarg)/2.0d0
2498: dqbdve=q1*(qb*ovb+oik*gbe/sqarg)
2499: dqbdvc=q1*(qb*ova+oikr*gbc/sqarg)
2500: c
2501: c weil's approx. for excess phase applied with backward-
2502: c euler integration
2503: c
2504: 410 cc=0.0d0
2505: cex=cbe
2506: gex=gbe
2507: if(mode.eq.1) go to 420
2508: if(td.eq.0.0d0) go to 420
2509: arg1=delta/td
2510: arg2=3.0d0*arg1
2511: arg1=arg2*arg1
2512: denom=1.0d0+arg1+arg2
2513: arg3=arg1/denom
2514: if(initf.ne.5) go to 411
2515: cexbc(lx1+loct)=cbe/qb
2516: cexbc(lx2+loct)=cexbc(lx1+loct)
2517: 411 cc=(cexbc(lx1+loct)*(1.0d0+delta/delold(2)+arg2)
2518: 1 -cexbc(lx2+loct)*delta/delold(2))/denom
2519: cex=cbe*arg3
2520: gex=gbe*arg3
2521: cexbc(lx0+loct)=cc+cex/qb
2522: c
2523: c determine dc incremental conductances
2524: c
2525: 420 cc=cc+(cex-cbc)/qb-cbc/brm-cbcn
2526: cb=cbe/bfm+cben+cbc/brm+cbcn
2527: gx=rbpr+rbpi/qb
2528: if(xjrb.eq.0.0d0) go to 430
2529: arg1=dmax1(cb/xjrb,1.0d-9)
2530: arg2=(-1.0d0+dsqrt(1.0d0+14.59025d0*arg1))/2.4317d0/dsqrt(arg1)
2531: arg1=dtan(arg2)
2532: gx=rbpr+3.0d0*rbpi*(arg1-arg2)/arg2/arg1/arg1
2533: 430 if(gx.ne.0.0d0) gx=1.0d0/gx
2534: gpi=gbe/bfm+gben
2535: gmu=gbc/brm+gbcn
2536: go=(gbc+(cex-cbc)*dqbdvc/qb)/qb
2537: gm=(gex-(cex-cbc)*dqbdve/qb)/qb-go
2538: if (mode.ne.1) go to 500
2539: if ((modedc.eq.2).and.(nosolv.ne.0)) go to 500
2540: if (initf.eq.4) go to 500
2541: go to 700
2542: c
2543: c charge storage elements
2544: c
2545: 500 tf=value(locm+24)
2546: tr=value(locm+33)
2547: czbe=value(locm+21)*area
2548: pe=value(locm+22)
2549: xme=value(locm+23)
2550: cdis=value(locm+32)
2551: ctot=value(locm+29)*area
2552: czbc=ctot*cdis
2553: czbx=ctot-czbc
2554: pc=value(locm+30)
2555: xmc=value(locm+31)
2556: fcpe=value(locm+46)
2557: czcs=value(locm+38)*area
2558: ps=value(locm+39)
2559: xms=value(locm+40)
2560: xtf=value(locm+25)
2561: ovtf=value(locm+26)
2562: xjtf=value(locm+27)*area
2563: if(tf.eq.0.0d0) go to 505
2564: if(vbe.le.0.0d0) go to 505
2565: argtf=0.0d0
2566: arg2=0.0d0
2567: arg3=0.0d0
2568: if(xtf.eq.0.0d0) go to 504
2569: argtf=xtf
2570: if(ovtf.ne.0.0d0) argtf=argtf*dexp(vbc*ovtf)
2571: arg2=argtf
2572: if(xjtf.eq.0.0d0) go to 503
2573: temp=cbe/(cbe+xjtf)
2574: argtf=argtf*temp*temp
2575: arg2=argtf*(3.0d0-temp-temp)
2576: 503 arg3=cbe*argtf*ovtf
2577: 504 cbe=cbe*(1.0d0+argtf)/qb
2578: gbe=(gbe*(1.0d0+arg2)-cbe*dqbdve)/qb
2579: geqcb=tf*(arg3-cbe*dqbdvc)/qb
2580: 505 if (vbe.ge.fcpe) go to 510
2581: arg=1.0d0-vbe/pe
2582: sarg=dexp(-xme*dlog(arg))
2583: qbe(lx0+loct)=tf*cbe+pe*czbe*(1.0d0-arg*sarg)/(1.0d0-xme)
2584: capbe=tf*gbe+czbe*sarg
2585: go to 520
2586: 510 f1=value(locm+47)
2587: f2=value(locm+48)
2588: f3=value(locm+49)
2589: czbef2=czbe/f2
2590: qbe(lx0+loct)=tf*cbe+czbe*f1+czbef2*(f3*(vbe-fcpe)
2591: 1 +(xme/(pe+pe))*(vbe*vbe-fcpe*fcpe))
2592: capbe=tf*gbe+czbef2*(f3+xme*vbe/pe)
2593: 520 fcpc=value(locm+50)
2594: f1=value(locm+51)
2595: f2=value(locm+52)
2596: f3=value(locm+53)
2597: if (vbc.ge.fcpc) go to 530
2598: arg=1.0d0-vbc/pc
2599: sarg=dexp(-xmc*dlog(arg))
2600: qbc(lx0+loct)=tr*cbc+pc*czbc*(1.0d0-arg*sarg)/(1.0d0-xmc)
2601: capbc=tr*gbc+czbc*sarg
2602: go to 540
2603: 530 czbcf2=czbc/f2
2604: qbc(lx0+loct)=tr*cbc+czbc*f1+czbcf2*(f3*(vbc-fcpc)
2605: 1 +(xmc/(pc+pc))*(vbc*vbc-fcpc*fcpc))
2606: capbc=tr*gbc+czbcf2*(f3+xmc*vbc/pc)
2607: 540 if(vbx.ge.fcpc) go to 550
2608: arg=1.0d0-vbx/pc
2609: sarg=dexp(-xmc*dlog(arg))
2610: qbx(lx0+loct)=pc*czbx*(1.0d0-arg*sarg)/(1.0d0-xmc)
2611: capbx=czbx*sarg
2612: go to 560
2613: 550 czbxf2=czbx/f2
2614: qbx(lx0+loct)=czbx*f1+czbxf2*(f3*(vbx-fcpc)+(xmc/(pc+pc))*
2615: 1 (vbx*vbx-fcpc*fcpc))
2616: capbx=czbxf2*(f3+xmc*vbx/pc)
2617: 560 if(vcs.ge.0.0d0) go to 570
2618: arg=1.0d0-vcs/ps
2619: sarg=dexp(-xms*dlog(arg))
2620: qcs(lx0+loct)=ps*czcs*(1.0d0-arg*sarg)/(1.0d0-xms)
2621: capcs=czcs*sarg
2622: go to 580
2623: 570 qcs(lx0+loct)=vcs*czcs*(1.0d0+xms*vcs/(2.0d0*ps))
2624: capcs=czcs*(1.0d0+xms*vcs/ps)
2625: c
2626: c store small-signal parameters
2627: c
2628: 580 if ((mode.eq.1).and.(modedc.eq.2).and.(nosolv.ne.0)) go to 700
2629: if (initf.ne.4) go to 600
2630: value(lx0+loct+9)=capbe
2631: value(lx0+loct+11)=capbc
2632: value(lx0+loct+13)=capcs
2633: value(lx0+loct+15)=capbx
2634: value(lx0+loct+17)=geqcb
2635: go to 1000
2636: c
2637: c transient analysis
2638: c
2639: 600 if (initf.ne.5) go to 610
2640: qbe(lx1+loct)=qbe(lx0+loct)
2641: qbc(lx1+loct)=qbc(lx0+loct)
2642: qbx(lx1+loct)=qbx(lx0+loct)
2643: qcs(lx1+loct)=qcs(lx0+loct)
2644: 610 call intgr8(geq,ceq,capbe,loct+8)
2645: geqcb=geqcb*ag(1)
2646: gpi=gpi+geq
2647: cb=cb+cqbe(lx0+loct)
2648: call intgr8(geq,ceq,capbc,loct+10)
2649: gmu=gmu+geq
2650: cb=cb+cqbc(lx0+loct)
2651: cc=cc-cqbc(lx0+loct)
2652: call intgr8(gccs,ceq,capcs,loct+12)
2653: ceqcs=type*(cqcs(lx0+loct)-vcs*gccs)
2654: call intgr8(geqbx,ceq,capbx,loct+14)
2655: ceqbx=type*(cqbx(lx0+loct)-vbx*geqbx)
2656: if (initf.ne.5) go to 700
2657: cqbe(lx1+loct)=cqbe(lx0+loct)
2658: cqbc(lx1+loct)=cqbc(lx0+loct)
2659: cqbx(lx1+loct)=cqbx(lx0+loct)
2660: cqcs(lx1+loct)=cqcs(lx0+loct)
2661: c
2662: c check convergence
2663: c
2664: 700 if (initf.ne.3) go to 710
2665: if (ioff.eq.0) go to 710
2666: go to 750
2667: 710 if (icheck.eq.1) go to 720
2668: tol=reltol*dmax1(dabs(cchat),dabs(cc))+abstol
2669: if (dabs(cchat-cc).gt.tol) go to 720
2670: tol=reltol*dmax1(dabs(cbhat),dabs(cb))+abstol
2671: if (dabs(cbhat-cb).le.tol) go to 750
2672: 720 noncon=noncon+1
2673: 750 vbeo(lx0+loct)=vbe
2674: vbco(lx0+loct)=vbc
2675: cco(lx0+loct)=cc
2676: cbo(lx0+loct)=cb
2677: gpio(lx0+loct)=gpi
2678: gmuo(lx0+loct)=gmu
2679: gmo(lx0+loct)=gm
2680: goo(lx0+loct)=go
2681: gxo(lx0+loct)=gx
2682: c
2683: c load current excitation vector
2684: c
2685: 900 ceqbe=type*(cc+cb-vbe*(gm+go+gpi)+vbc*(go-geqcb))
2686: ceqbc=type*(-cc+vbe*(gm+go)-vbc*(gmu+go))
2687: value(lvn+node2)=value(lvn+node2)-ceqbx
2688: value(lvn+node4)=value(lvn+node4)+ceqcs+ceqbx+ceqbc
2689: value(lvn+node5)=value(lvn+node5)-ceqbe-ceqbc
2690: value(lvn+node6)=value(lvn+node6)+ceqbe
2691: value(lvn+node7)=value(lvn+node7)-ceqcs
2692: c
2693: c load y matrix
2694: c
2695: locy=lynl+nodplc(loc+24)
2696: value(locy)=value(locy)+gcpr
2697: locy=lynl+nodplc(loc+25)
2698: value(locy)=value(locy)+gx+geqbx
2699: locy=lynl+nodplc(loc+26)
2700: value(locy)=value(locy)+gepr
2701: locy=lynl+nodplc(loc+27)
2702: value(locy)=value(locy)+gmu+go+gcpr+gccs+geqbx
2703: locy=lynl+nodplc(loc+28)
2704: value(locy)=value(locy)+gx +gpi+gmu+geqcb
2705: locy=lynl+nodplc(loc+29)
2706: value(locy)=value(locy)+gpi+gepr+gm+go
2707: locy=lynl+nodplc(loc+10)
2708: value(locy)=value(locy)-gcpr
2709: locy=lynl+nodplc(loc+11)
2710: value(locy)=value(locy)-gx
2711: locy=lynl+nodplc(loc+12)
2712: value(locy)=value(locy)-gepr
2713: locy=lynl+nodplc(loc+13)
2714: value(locy)=value(locy)-gcpr
2715: locy=lynl+nodplc(loc+14)
2716: value(locy)=value(locy)-gmu+gm
2717: locy=lynl+nodplc(loc+15)
2718: value(locy)=value(locy)-gm-go
2719: locy=lynl+nodplc(loc+16)
2720: value(locy)=value(locy)-gx
2721: locy=lynl+nodplc(loc+17)
2722: value(locy)=value(locy)-gmu-geqcb
2723: locy=lynl+nodplc(loc+18)
2724: value(locy)=value(locy)-gpi
2725: locy=lynl+nodplc(loc+19)
2726: value(locy)=value(locy)-gepr
2727: locy=lynl+nodplc(loc+20)
2728: value(locy)=value(locy)-go+geqcb
2729: locy=lynl+nodplc(loc+21)
2730: value(locy)=value(locy)-gpi-gm-geqcb
2731: locy=lynl+nodplc(loc+31)
2732: value(locy)=value(locy)+gccs
2733: locy=lynl+nodplc(loc+32)
2734: value(locy)=value(locy)-gccs
2735: locy=lynl+nodplc(loc+33)
2736: value(locy)=value(locy)-gccs
2737: locy=lynl+nodplc(loc+34)
2738: value(locy)=value(locy)-geqbx
2739: locy=lynl+nodplc(loc+35)
2740: value(locy)=value(locy)-geqbx
2741: 1000 loc=nodplc(loc)
2742: go to 10
2743: end
2744: subroutine fetlim(vnew,vold,vto,icheck)
2745: c
2746: c *** fetlim is not used in this version ***
2747: c * if problems arrise with the conver- *
2748: c * gence of MOSFET circuit it should be *
2749: c * re-installed. R.Newton. *
2750: c *** ***
2751: c
2752: return
2753: end
2754: subroutine jfet
2755: implicit double precision (a-h,o-z)
2756: c
2757: c this routine processes jfets for dc and transient analyses.
2758: c
2759: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
2760: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
2761: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
2762: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
2763: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
2764: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
2765: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
2766: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
2767: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
2768: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
2769: 2 itemno,nosolv,ipostp,iscrch
2770: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
2771: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
2772: common /blank/ value(1000)
2773: integer nodplc(64)
2774: complex*16 cvalue(32)
2775: equivalence (value(1),nodplc(1),cvalue(1))
2776: c
2777: c
2778: dimension vgso(1),vgdo(1),cgo(1),cdo(1),cgdo(1),gmo(1),gdso(1),
2779: 1 ggso(1),ggdo(1),qgs(1),cqgs(1),qgd(1),cqgd(1)
2780: equivalence (vgso(1),value( 1)),(vgdo(1),value( 2)),
2781: 1 (cgo (1),value( 3)),(cdo (1),value( 4)),
2782: 2 (cgdo(1),value( 5)),(gmo (1),value( 6)),
2783: 3 (gdso(1),value( 7)),(ggso(1),value( 8)),
2784: 4 (ggdo(1),value( 9)),(qgs (1),value(10)),
2785: 5 (cqgs(1),value(11)),(qgd (1),value(12)),
2786: 6 (cqgd(1),value(13))
2787: c
2788: c
2789: loc=locate(13)
2790: 10 if (loc.eq.0) return
2791: locv=nodplc(loc+1)
2792: node1=nodplc(loc+2)
2793: node2=nodplc(loc+3)
2794: node3=nodplc(loc+4)
2795: node4=nodplc(loc+5)
2796: node5=nodplc(loc+6)
2797: locm=nodplc(loc+7)
2798: ioff=nodplc(loc+8)
2799: type=nodplc(locm+2)
2800: locm=nodplc(locm+1)
2801: loct=nodplc(loc+19)
2802: c
2803: c dc model parameters
2804: c
2805: area=value(locv+1)
2806: vto=value(locm+1)
2807: beta=value(locm+2)*area
2808: xlamb=value(locm+3)
2809: gdpr=value(locm+4)*area
2810: gspr=value(locm+5)*area
2811: csat=value(locm+9)*area
2812: vcrit=value(locm+16)
2813: c
2814: c initialization
2815: c
2816: icheck=1
2817: go to (100,20,30,50,60,70), initf
2818: 20 if(mode.ne.1.or.modedc.ne.2.or.nosolv.eq.0) go to 25
2819: vds=type*value(locv+2)
2820: vgs=type*value(locv+3)
2821: vgd=vgs-vds
2822: go to 300
2823: 25 if(ioff.ne.0) go to 40
2824: vgs=-1.0d0
2825: vgd=-1.0d0
2826: go to 300
2827: 30 if (ioff.eq.0) go to 100
2828: 40 vgs=0.0d0
2829: vgd=0.0d0
2830: go to 300
2831: 50 vgs=vgso(lx0+loct)
2832: vgd=vgdo(lx0+loct)
2833: go to 300
2834: 60 vgs=vgso(lx1+loct)
2835: vgd=vgdo(lx1+loct)
2836: go to 300
2837: 70 xfact=delta/delold(2)
2838: vgso(lx0+loct)=vgso(lx1+loct)
2839: vgs=(1.0d0+xfact)*vgso(lx1+loct)-xfact*vgso(lx2+loct)
2840: vgdo(lx0+loct)=vgdo(lx1+loct)
2841: vgd=(1.0d0+xfact)*vgdo(lx1+loct)-xfact*vgdo(lx2+loct)
2842: cgo(lx0+loct)=cgo(lx1+loct)
2843: cdo(lx0+loct)=cdo(lx1+loct)
2844: cgdo(lx0+loct)=cgdo(lx1+loct)
2845: gmo(lx0+loct)=gmo(lx1+loct)
2846: gdso(lx0+loct)=gdso(lx1+loct)
2847: ggso(lx0+loct)=ggso(lx1+loct)
2848: ggdo(lx0+loct)=ggdo(lx1+loct)
2849: go to 110
2850: c
2851: c compute new nonlinear branch voltages
2852: c
2853: 100 vgs=type*(value(lvnim1+node2)-value(lvnim1+node5))
2854: vgd=type*(value(lvnim1+node2)-value(lvnim1+node4))
2855: 110 delvgs=vgs-vgso(lx0+loct)
2856: delvgd=vgd-vgdo(lx0+loct)
2857: delvds=delvgs-delvgd
2858: cghat=cgo(lx0+loct)+ggdo(lx0+loct)*delvgd+ggso(lx0+loct)*delvgs
2859: cdhat=cdo(lx0+loct)+gmo(lx0+loct)*delvgs+gdso(lx0+loct)*delvds
2860: 1 -ggdo(lx0+loct)*delvgd
2861: c
2862: c bypass if solution has not changed
2863: c
2864: if (initf.eq.6) go to 200
2865: tol=reltol*dmax1(dabs(vgs),dabs(vgso(lx0+loct)))+vntol
2866: if (dabs(delvgs).ge.tol) go to 200
2867: tol=reltol*dmax1(dabs(vgd),dabs(vgdo(lx0+loct)))+vntol
2868: if (dabs(delvgd).ge.tol) go to 200
2869: tol=reltol*dmax1(dabs(cghat),dabs(cgo(lx0+loct)))+abstol
2870: if (dabs(cghat-cgo(lx0+loct)).ge.tol) go to 200
2871: tol=reltol*dmax1(dabs(cdhat),dabs(cdo(lx0+loct)))+abstol
2872: if (dabs(cdhat-cdo(lx0+loct)).ge.tol) go to 200
2873: vgs=vgso(lx0+loct)
2874: vgd=vgdo(lx0+loct)
2875: vds=vgs-vgd
2876: cg=cgo(lx0+loct)
2877: cd=cdo(lx0+loct)
2878: cgd=cgdo(lx0+loct)
2879: gm=gmo(lx0+loct)
2880: gds=gdso(lx0+loct)
2881: ggs=ggso(lx0+loct)
2882: ggd=ggdo(lx0+loct)
2883: go to 900
2884: c
2885: c limit nonlinear branch voltages
2886: c
2887: 200 icheck=0
2888: call pnjlim(vgs,vgso(lx0+loct),vt,vcrit,icheck)
2889: call pnjlim(vgd,vgdo(lx0+loct),vt,vcrit,icheck)
2890: call fetlim(vgs,vgso(lx0+loct),vto,icheck)
2891: call fetlim(vgd,vgdo(lx0+loct),vto,icheck)
2892: c
2893: c determine dc current and derivatives
2894: c
2895: 300 vds=vgs-vgd
2896: if (vgs.gt.-5.0d0*vt) go to 310
2897: ggs=-csat/vgs+gmin
2898: cg=ggs*vgs
2899: go to 320
2900: 310 evgs=dexp(vgs/vt)
2901: ggs=csat*evgs/vt+gmin
2902: cg=csat*(evgs-1.0d0)+gmin*vgs
2903: 320 if (vgd.gt.-5.0d0*vt) go to 330
2904: ggd=-csat/vgd+gmin
2905: cgd=ggd*vgd
2906: go to 340
2907: 330 evgd=dexp(vgd/vt)
2908: ggd=csat*evgd/vt+gmin
2909: cgd=csat*(evgd-1.0d0)+gmin*vgd
2910: 340 cg=cg+cgd
2911: c
2912: c compute drain current and derivitives for normal mode
2913: c
2914: 400 if (vds.lt.0.0d0) go to 450
2915: vgst=vgs-vto
2916: c
2917: c normal mode, cutoff region
2918: c
2919: if (vgst.gt.0.0d0) go to 410
2920: cdrain=0.0d0
2921: gm=0.0d0
2922: gds=0.0d0
2923: go to 490
2924: c
2925: c normal mode, saturation region
2926: c
2927: 410 betap=beta*(1.0d0+xlamb*vds)
2928: twob=betap+betap
2929: if (vgst.gt.vds) go to 420
2930: cdrain=betap*vgst*vgst
2931: gm=twob*vgst
2932: gds=xlamb*beta*vgst*vgst
2933: go to 490
2934: c
2935: c normal mode, linear region
2936: c
2937: 420 cdrain=betap*vds*(vgst+vgst-vds)
2938: gm=twob*vds
2939: gds=twob*(vgst-vds)+xlamb*beta*vds*(vgst+vgst-vds)
2940: go to 490
2941: c
2942: c compute drain current and derivitives for inverse mode
2943: c
2944: 450 vgdt=vgd-vto
2945: c
2946: c inverse mode, cutoff region
2947: c
2948: if (vgdt.gt.0.0d0) go to 460
2949: cdrain=0.0d0
2950: gm=0.0d0
2951: gds=0.0d0
2952: go to 490
2953: c
2954: c inverse mode, saturation region
2955: c
2956: 460 betap=beta*(1.0d0-xlamb*vds)
2957: twob=betap+betap
2958: if (vgdt.gt.-vds) go to 470
2959: cdrain=-betap*vgdt*vgdt
2960: gm=-twob*vgdt
2961: gds=xlamb*beta*vgdt*vgdt-gm
2962: go to 490
2963: c
2964: c inverse mode, linear region
2965: c
2966: 470 cdrain=betap*vds*(vgdt+vgdt+vds)
2967: gm=twob*vds
2968: gds=twob*vgdt-xlamb*beta*vds*(vgdt+vgdt+vds)
2969: c
2970: c compute equivalent drain current source
2971: c
2972: 490 cd=cdrain-cgd
2973: if (mode.ne.1) go to 500
2974: if ((modedc.eq.2).and.(nosolv.ne.0)) go to 500
2975: if (initf.eq.4) go to 500
2976: go to 700
2977: c
2978: c charge storage elements
2979: c
2980: 500 czgs=value(locm+6)*area
2981: czgd=value(locm+7)*area
2982: phib=value(locm+8)
2983: twop=phib+phib
2984: fcpb=value(locm+12)
2985: fcpb2=fcpb*fcpb
2986: f1=value(locm+13)
2987: f2=value(locm+14)
2988: f3=value(locm+15)
2989: czgsf2=czgs/f2
2990: czgdf2=czgd/f2
2991: if (vgs.ge.fcpb) go to 510
2992: sarg=dsqrt(1.0d0-vgs/phib)
2993: qgs(lx0+loct)=twop*czgs*(1.0d0-sarg)
2994: capgs=czgs/sarg
2995: go to 520
2996: 510 qgs(lx0+loct)=czgs*f1+czgsf2*(f3*(vgs-fcpb)
2997: 1 +(vgs*vgs-fcpb2)/(twop+twop))
2998: capgs=czgsf2*(f3+vgs/twop)
2999: 520 if (vgd.ge.fcpb) go to 530
3000: sarg=dsqrt(1.0d0-vgd/phib)
3001: qgd(lx0+loct)=twop*czgd*(1.0d0-sarg)
3002: capgd=czgd/sarg
3003: go to 560
3004: 530 qgd(lx0+loct)=czgd*f1+czgdf2*(f3*(vgd-fcpb)
3005: 1 +(vgd*vgd-fcpb2)/(twop+twop))
3006: capgd=czgdf2*(f3+vgd/twop)
3007: c
3008: c store small-signal parameters
3009: c
3010: 560 if ((mode.eq.1).and.(modedc.eq.2).and.(nosolv.ne.0)) go to 700
3011: if (initf.ne.4) go to 600
3012: value(lx0+loct+9)=capgs
3013: value(lx0+loct+11)=capgd
3014: go to 1000
3015: c
3016: c transient analysis
3017: c
3018: 600 if (initf.ne.5) go to 610
3019: qgs(lx1+loct)=qgs(lx0+loct)
3020: qgd(lx1+loct)=qgd(lx0+loct)
3021: 610 call intgr8(geq,ceq,capgs,loct+9)
3022: ggs=ggs+geq
3023: cg=cg+cqgs(lx0+loct)
3024: call intgr8(geq,ceq,capgd,loct+11)
3025: ggd=ggd+geq
3026: cg=cg+cqgd(lx0+loct)
3027: cd=cd-cqgd(lx0+loct)
3028: cgd=cgd+cqgd(lx0+loct)
3029: if (initf.ne.5) go to 700
3030: cqgs(lx1+loct)=cqgs(lx0+loct)
3031: cqgd(lx1+loct)=cqgd(lx0+loct)
3032: c
3033: c check convergence
3034: c
3035: 700 if (initf.ne.3) go to 710
3036: if (ioff.eq.0) go to 710
3037: go to 750
3038: 710 if (icheck.eq.1) go to 720
3039: tol=reltol*dmax1(dabs(cghat),dabs(cg))+abstol
3040: if (dabs(cghat-cg).ge.tol) go to 720
3041: tol=reltol*dmax1(dabs(cdhat),dabs(cd))+abstol
3042: if (dabs(cdhat-cd).le.tol) go to 750
3043: 720 noncon=noncon+1
3044: 750 vgso(lx0+loct)=vgs
3045: vgdo(lx0+loct)=vgd
3046: cgo(lx0+loct)=cg
3047: cdo(lx0+loct)=cd
3048: cgdo(lx0+loct)=cgd
3049: gmo(lx0+loct)=gm
3050: gdso(lx0+loct)=gds
3051: ggso(lx0+loct)=ggs
3052: ggdo(lx0+loct)=ggd
3053: c
3054: c load current vector
3055: c
3056: 900 ceqgd=type*(cgd-ggd*vgd)
3057: ceqgs=type*((cg-cgd)-ggs*vgs)
3058: cdreq=type*((cd+cgd)-gds*vds-gm*vgs)
3059: value(lvn+node2)=value(lvn+node2)-ceqgs-ceqgd
3060: value(lvn+node4)=value(lvn+node4)-cdreq+ceqgd
3061: value(lvn+node5)=value(lvn+node5)+cdreq+ceqgs
3062: c
3063: c load y matrix
3064: c
3065: locy=lynl+nodplc(loc+20)
3066: value(locy)=value(locy)+gdpr
3067: locy=lynl+nodplc(loc+21)
3068: value(locy)=value(locy)+ggd+ggs
3069: locy=lynl+nodplc(loc+22)
3070: value(locy)=value(locy)+gspr
3071: locy=lynl+nodplc(loc+23)
3072: value(locy)=value(locy)+gdpr+gds+ggd
3073: locy=lynl+nodplc(loc+24)
3074: value(locy)=value(locy)+gspr+gds+gm+ggs
3075: locy=lynl+nodplc(loc+9)
3076: value(locy)=value(locy)-gdpr
3077: locy=lynl+nodplc(loc+10)
3078: value(locy)=value(locy)-ggd
3079: locy=lynl+nodplc(loc+11)
3080: value(locy)=value(locy)-ggs
3081: locy=lynl+nodplc(loc+12)
3082: value(locy)=value(locy)-gspr
3083: locy=lynl+nodplc(loc+13)
3084: value(locy)=value(locy)-gdpr
3085: locy=lynl+nodplc(loc+14)
3086: value(locy)=value(locy)+gm-ggd
3087: locy=lynl+nodplc(loc+15)
3088: value(locy)=value(locy)-gds-gm
3089: locy=lynl+nodplc(loc+16)
3090: value(locy)=value(locy)-ggs-gm
3091: locy=lynl+nodplc(loc+17)
3092: value(locy)=value(locy)-gspr
3093: locy=lynl+nodplc(loc+18)
3094: value(locy)=value(locy)-gds
3095: 1000 loc=nodplc(loc)
3096: go to 10
3097: end
3098: subroutine mosfet
3099: implicit double precision (a-h,o-z)
3100: c
3101: c this routine processes mosfets for dc and transient analyses.
3102: c
3103: common /tabinf/ ielmnt,isbckt,nsbckt,iunsat,nunsat,itemps,numtem,
3104: 1 isens,nsens,ifour,nfour,ifield,icode,idelim,icolum,insize,
3105: 2 junode,lsbkpt,numbkp,iorder,jmnode,iur,iuc,ilc,ilr,numoff,isr,
3106: 3 nmoffc,iseq,iseq1,neqn,nodevs,ndiag,iswap,iequa,macins,lvnim1,
3107: 4 lx0,lvn,lynl,lyu,lyl,lx1,lx2,lx3,lx4,lx5,lx6,lx7,ld0,ld1,ltd,
3108: 5 imynl,imvn,lcvn,loutpt,nsnod,nsmat,nsval,icnod,icmat,icval
3109: common /cirdat/ locate(50),jelcnt(50),nunods,ncnods,numnod,nstop,
3110: 1 nut,nlt,nxtrm,ndist,ntlin,ibr,numvs
3111: common /mosarg/ gamma,beta,vto,phi,cox,vbi,xnfs,xnsub,xd,xj,xl,
3112: 1 xlamda,utra,uexp,vbp,von,vdsat,theta,vcrit,vtra,gleff,cdrain
3113: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
3114: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
3115: 2 itemno,nosolv,ipostp,iscrch
3116: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
3117: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
3118: common /blank/ value(1000)
3119: integer nodplc(64)
3120: complex*16 cvalue(32)
3121: equivalence (value(1),nodplc(1),cvalue(1))
3122: c
3123: c
3124: dimension vbdo(1),vbso(1),vgbo(1),gdgo(1),cdo(1),cbo(1),
3125: 1 gddo(1),gdso(1),gbgo(1),gbdo(1),gbso(1),qb(1),cqb(1),qg(1),
3126: 2 cqg(1),qd(1),cqd(1)
3127: c.. note: for direct indexing with 'value', use, e.g. loct+2 to find vgbo
3128: equivalence (vbdo (1),value( 1)),(vbso (1),value( 2)),
3129: 1 (vgbo (1),value( 3)),
3130: 2 (cdo (1),value( 5)),(cbo (1),value( 6)),
3131: 3 (gddo (1),value( 7)),(gdgo (1),value(8)),
3132: 4 (gdso (1),value( 9)),(gbgo (1),value(10)),
3133: 5 (gbdo (1),value(11)),(gbso (1),value(12)),
3134: 6 (qb (1),value(13)),(cqb (1),value(14)),
3135: 7 (qg (1),value(15)),(cqg (1),value(16)),
3136: 8 (qd (1),value(17)),(cqd (1),value(18))
3137: c
3138: c
3139: loc=locate(14)
3140: 10 if (loc.eq.0) return
3141: locm=nodplc(loc+8)
3142: if(nodplc(locm+2).ne.0) go to 15
3143: call gasfet(loc)
3144: go to 1000
3145: 15 locv=nodplc(loc+1)
3146: node1=nodplc(loc+2)
3147: node2=nodplc(loc+3)
3148: node3=nodplc(loc+4)
3149: node4=nodplc(loc+5)
3150: node5=nodplc(loc+6)
3151: node6=nodplc(loc+7)
3152: ioff=nodplc(loc+9)
3153: type=nodplc(locm+2)
3154: locm=nodplc(locm+1)
3155: loct=nodplc(loc+26)
3156: c
3157: c dc model parameters
3158: c
3159: xj=value(locm+19)
3160: xl=value(locv+1)-2.0d0*value(locm+20)
3161: xw=value(locv+2)-2.0d0*value(locm+36)
3162: devmod=value(locv+8)
3163: vto=type*value(locm+1)
3164: beta=value(locm+2)*xw/xl
3165: gamma=value(locm+3)
3166: phi=value(locm+4)
3167: xlamda=value(locm+5)
3168: csat=value(locm+15)
3169: ad=value(locv+3)
3170: as=value(locv+4)
3171: cdsat=csat*ad
3172: cssat=csat*as
3173: gdpr=value(locv+11)
3174: gspr=value(locv+12)
3175: covlgs=value(locm+8)*xw
3176: covlgd=value(locm+9)*xw
3177: covlgb=value(locm+10)*xl
3178: cox=value(locm+13)
3179: xnsub=value(locm+16)
3180: xnfs=value(locm+18)
3181: vbp=value(locm+24)
3182: uexp=value(locm+25)
3183: utra=value(locm+26)
3184: vbi=type*value(locm+34)
3185: xd=value(locm+35)
3186: vcrit=value(locm+37)*xl
3187: vtra=value(locm+38)*xl
3188: theta=value(locm+39)
3189: gleff=value(locm+40)
3190: c
3191: c initialization
3192: c
3193: icheck=1
3194: go to (100,20,30,50,60,70), initf
3195: 20 if(mode.ne.1.or.modedc.ne.2.or.nosolv.eq.0) go to 25
3196: vbs=type*value(locv+7)
3197: vbd=type*value(locv+5)-vbs
3198: vgb=type*value(locv+6)-vbs
3199: go to 300
3200: 25 if(ioff.ne.0) go to 40
3201: vbs=0.0d0
3202: vbd=0.0d0
3203: vgb=vto
3204: go to 300
3205: 30 if (ioff.eq.0) go to 100
3206: 40 vbs=0.0d0
3207: vbd=0.0d0
3208: vgb=0.0d0
3209: go to 300
3210: 50 vbs=vbso(lx0+loct)
3211: vbd=vbdo(lx0+loct)
3212: vgb=vgbo(lx0+loct)
3213: go to 300
3214: 60 vbs=vbso(lx1+loct)
3215: vbd=vbdo(lx1+loct)
3216: vgb=vgbo(lx1+loct)
3217: go to 300
3218: 70 xfact=delta/delold(2)
3219: vbso(lx0+loct)=vbso(lx1+loct)
3220: vbs=(1.0d0+xfact)*vbso(lx1+loct)-xfact*vbso(lx2+loct)
3221: vbdo(lx0+loct)=vbdo(lx1+loct)
3222: vbd=(1.0d0+xfact)*vbdo(lx1+loct)-xfact*vbdo(lx2+loct)
3223: vgbo(lx0+loct)=vgbo(lx1+loct)
3224: vgb=(1.0d0+xfact)*vgbo(lx1+loct)-xfact*vgbo(lx2+loct)
3225: cdo(lx0+loct)=cdo(lx1+loct)
3226: cbo(lx0+loct)=cbo(lx1+loct)
3227: gdgo(lx0+loct)=gdgo(lx1+loct)
3228: gddo(lx0+loct)=gddo(lx1+loct)
3229: gdso(lx0+loct)=gdso(lx1+loct)
3230: gbgo(lx0+loct)=gbgo(lx1+loct)
3231: gbdo(lx0+loct)=gbdo(lx1+loct)
3232: gbso(lx0+loct)=gbso(lx1+loct)
3233: go to 110
3234: c
3235: c compute new nonlinear branch voltages
3236: c
3237: 100 vbs=type*(value(lvnim1+node4)-value(lvnim1+node6))
3238: vbd=type*(value(lvnim1+node4)-value(lvnim1+node5))
3239: vgb=type*(value(lvnim1+node2)-value(lvnim1+node4))
3240: 110 delvbs=vbs-vbso(lx0+loct)
3241: delvbd=vbd-vbdo(lx0+loct)
3242: delvgb=vgb-vgbo(lx0+loct)
3243: cdhat=cdo(lx0+loct)+gdgo(lx0+loct)*delvgb-gddo(lx0+loct)*delvbd
3244: 1 -gdso(lx0+loct)*delvbs
3245: cbhat=cbo(lx0+loct)+gbgo(lx0+loct)*delvgb-gbdo(lx0+loct)*delvbd
3246: 1 -gbso(lx0+loct)*delvbs
3247: c
3248: c bypass if solution has not changed
3249: c
3250: c********** kill bypass for now!!!!!
3251: if (6 .eq.6) go to 200
3252: tol=reltol*dmax1(dabs(vbs),dabs(vbso(lx0+loct)))+vntol
3253: if (dabs(delvbs).ge.tol) go to 200
3254: tol=reltol*dmax1(dabs(vbd),dabs(vbdo(lx0+loct)))+vntol
3255: if (dabs(delvbd).ge.tol) go to 200
3256: tol=reltol*dmax1(dabs(vgb),dabs(vgbo(lx0+loct)))+vntol
3257: if (dabs(delvgb).ge.tol) go to 200
3258: tol=reltol*dmax1(dabs(cdhat),dabs(cdo(lx0+loct)))+abstol
3259: if (dabs(cdhat-cdo(lx0+loct)).ge.tol) go to 200
3260: tol=reltol*dmax1(dabs(cbhat),dabs(cbo(lx0+loct)))+abstol
3261: if (dabs(cbhat-(cbo(lx0+loct))).ge.tol) go to 200
3262: vbd=vbdo(lx0+loct)
3263: vbs=vbso(lx0+loct)
3264: vgb=vgbo(lx0+loct)
3265: cdrain=cdo(lx0+loct)
3266: cbulk=cbo(lx0+loct)
3267: gccdg=gdgo(lx0+loct)
3268: gccdd=gddo(lx0+loct)
3269: gccds=gdso(lx0+loct)
3270: gccbg=gbgo(lx0+loct)
3271: gccbd=gbdo(lx0+loct)
3272: gccbs=gbso(lx0+loct)
3273: go to 900
3274: c
3275: c limit nonlinear branch voltages
3276: c
3277: 200 von=type*value(locv+9)
3278: icheck=0
3279: call fetlim(vgb,vgbo(lx0+loct),von,icheck)
3280: vcornr=0.0d0
3281: c if(vbs.gt.0.0d0) vcornr=vt*dlog(vt/(root2*cssat))
3282: call pnjlim(vbs,vbso(lx0+loct),vt,vcornr,icheck)
3283: c vbs=dmax1(vbso(lx0+loct)-10.0d0,vbs)
3284: vcornr=0.0d0
3285: c if(vbd.gt.0.0d0) vcornr=vt*dlog(vt/(root2*cdsat))
3286: call pnjlim(vbd,vbdo(lx0+loct),vt,vcornr,icheck)
3287: c vbd=dmax1(vbdo(lx0+loct)-10.0d0,vbd)
3288: c
3289: c determine bulk-drain and bulk-source diode terms
3290: c
3291: 300 fivevt=-5.0d0*vt
3292: if (vbs.gt.fivevt) go to 310
3293: geqbs=-cssat/vbs+gmin
3294: cbulk=geqbs*vbs
3295: go to 320
3296: 310 evbs=dexp(vbs/vt)
3297: geqbs=cssat*evbs/vt+gmin
3298: cbulk=cssat*(evbs-1.0d0)+gmin*vbs
3299: 320 if (vbd.gt.fivevt) go to 330
3300: geqbd=-cdsat/vbd+gmin
3301: cbd=geqbd*vbd
3302: cbulk=cbulk+cbd
3303: go to 340
3304: 330 evbd=dexp(vbd/vt)
3305: geqbd=cdsat*evbd/vt+gmin
3306: cbd=cdsat*(evbd-1.0d0)+gmin*vbd
3307: cbulk=cbulk+cbd
3308: c.. cbd must also be subtracted from drain current
3309: 340 continue
3310: gccdd=geqbd
3311: gccbd=-geqbd
3312: gccss=geqbs
3313: gccbs=-geqbs
3314: if (mode.ne.1) go to 350
3315: c.. zero out some conductances and cgate
3316: cgate=0.0d0
3317: gccgg=0.0d0
3318: gccgd=0.0d0
3319: gccgs=0.0d0
3320: gccbg=0.0d0
3321: c
3322: c compute drain current and derivatives
3323: c
3324: 350 cox=cox*xl*xw
3325: if(vbd.gt.vbs) go to 360
3326: c.. normal operation
3327: devmod=1.0d0
3328: call calcq(vgb,vbd,vbs,qgate,qchan,qbulk,
3329: 1 ccgg,ccgd,ccgs,ccbg,ccbd,ccbs,didvg,didvd,didvs)
3330: didvg=beta*didvg
3331: didvd=beta*didvd
3332: didvs=beta*didvs
3333: go to 370
3334: c.. inverted operation
3335: 360 devmod=-1.0d0
3336: call calcq(vgb,vbs,vbd,qgate,qchan,qbulk,
3337: 1 ccgg,ccgs,ccgd,ccbg,ccbs,ccbd,didvg,didvs,didvd)
3338: didvg=-beta*didvg
3339: didvd=-beta*didvd
3340: didvs=-beta*didvs
3341: cdrain=-cdrain
3342: 370 cdrain=beta*cdrain-cbd
3343: c if(mode.ne.1) write(6,6666) qgate,qchan,qbulk,time,delta
3344: 6666 format(' qg qc qb',1p3e11.3,' time delta ',2e11.3)
3345: value(locv+8)=devmod
3346: value(locv+9)=type*von
3347: value(locv+10)=type*vdsat
3348: if(mode.ne.1) go to 500
3349: if ((modedc.eq.2).and.(nosolv.ne.0)) go to 500
3350: if (initf.eq.4) go to 500
3351: gccdg=didvg
3352: gccdd=gccdd+didvd
3353: gccds=didvs
3354: gccsg=-didvg
3355: gccsd=-didvd
3356: gccss=gccss-didvs
3357: go to 700
3358: c
3359: c charge storage elements
3360: c
3361: c.. bulk-drain and bulk-source depletion capacitances
3362: 500 czbd=value(locm+11)*ad
3363: czbs=value(locm+12)*as
3364: phib=value(locm+14)
3365: twop=phib+phib
3366: fcpb=value(locm+29)
3367: if(vbs.lt.fcpb.and.vbd.lt.fcpb) go to 505
3368: fcpb2=fcpb*fcpb
3369: f1=value(locm+30)
3370: f2=value(locm+31)
3371: f3=value(locm+32)
3372: czbsf2=czbs/f2
3373: czbdf2=czbd/f2
3374: if (vbs.ge.fcpb) go to 510
3375: 505 sarg=dsqrt(1.0d0-vbs/phib)
3376: qbs=twop*czbs*(1.0d0-sarg)
3377: capbs=czbs/sarg
3378: go to 520
3379: 510 qbs=czbs*f1+czbsf2*(f3*(vbs-fcpb)
3380: 1 +(vbs*vbs-fcpb2)/(twop+twop))
3381: capbs=czbsf2*(f3+vbs/twop)
3382: 520 if (vbd.ge.fcpb) go to 530
3383: sarg=dsqrt(1.0d0-vbd/phib)
3384: qbd=twop*czbd*(1.0d0-sarg)
3385: capbd=czbd/sarg
3386: go to 540
3387: 530 qbd=czbd*f1+czbdf2*(f3*(vbd-fcpb)
3388: 1 +(vbd*vbd-fcpb2)/(twop+twop))
3389: capbd=czbdf2*(f3+vbd/twop)
3390: c.. bulk and channel charge (plus overlaps)
3391: 540 qgd=covlgd*(vgb+vbd)
3392: qgs=covlgs*(vgb+vbs)
3393: qgb=covlgb*vgb
3394: qg(lx0+loct)=qgate+qgb+qgd+qgs
3395: qd(lx0+loct)=qchan*0.5d0-qgd-qbd
3396: qb(lx0+loct)=qbulk+qbd+qbs-qgb
3397: c
3398: c store small-signal parameters
3399: c
3400: 590 if ((mode.eq.1).and.(modedc.eq.2).and.(nosolv.ne.0)) go to 900
3401: if (initf.ne.4) go to 600
3402: value(lx0+loct)=didvg
3403: value(lx0+loct+1)=didvd
3404: value(lx0+loct+2)=didvs
3405: value(lx0+loct+3)=geqbd
3406: c.. cdrain is used in printing as well as noise calculation
3407: value(lx0+loct+4)=cdrain
3408: value(lx0+loct+5)=geqbs
3409: c.. (loct+6 not used)
3410: c.. this is the 'gm' term used in the noise calculation
3411: value(lx0+loct+7)=didvg
3412: value(lx0+loct+8)=ccgg
3413: value(lx0+loct+9)=ccgd
3414: value(lx0+loct+10)=ccgs
3415: value(lx0+loct+11)=ccbg
3416: value(lx0+loct+12)=ccbd
3417: value(lx0+loct+13)=ccbs
3418: value(lx0+loct+14)=capbd
3419: value(lx0+loct+15)=capbs
3420: go to 1000
3421: c
3422: c transient analysis
3423: c
3424: 600 if (initf.ne.5) go to 610
3425: qb(lx1+loct)=qb(lx0+loct)
3426: qg(lx1+loct)=qg(lx0+loct)
3427: qd(lx1+loct)=qd(lx0+loct)
3428: c.. integrate qb
3429: 610 call intgr8(geq,ceq,0.0d0,loct+12)
3430: c.. integrate qg
3431: call intgr8(geq,ceq,0.0d0,loct+14)
3432: c.. integrate qd
3433: call intgr8(geq,ceq,0.0d0,loct+16)
3434: c.. divvey up the channel charge 50/50 to source and drain
3435: c.. note that symmetry also precludes need for 'devmod' decisions
3436: gccg2=-0.5d0*(ccgg+ccbg)*ag(1)
3437: gccd2=-0.5d0*(ccgd+ccbd)*ag(1)
3438: gccs2=-0.5d0*(ccgs+ccbs)*ag(1)
3439: gccdg=gccg2+didvg-covlgd*ag(1)
3440: gccdd=gccdd+gccd2+didvd+(capbd+covlgd)*ag(1)
3441: gccds=gccs2+didvs
3442: gccsg=gccg2-didvg-covlgs*ag(1)
3443: gccsd=gccd2-didvd
3444: gccss=gccss+gccs2-didvs+(capbs+covlgs)*ag(1)
3445: gccgg=(ccgg+covlgd+covlgs+covlgb)*ag(1)
3446: gccgd=(ccgd-covlgd)*ag(1)
3447: gccgs=(ccgs-covlgs)*ag(1)
3448: gccbg=(ccbg-covlgb)*ag(1)
3449: gccbd=gccbd+(ccbd-capbd)*ag(1)
3450: gccbs=gccbs+(ccbs-capbs)*ag(1)
3451: cgate=cqg(lx0+loct)
3452: cbulk=cbulk+cqb(lx0+loct)
3453: cdrain=cdrain+cqd(lx0+loct)
3454: if (initf.ne.5) go to 700
3455: cqb(lx1+loct)=cqb(lx0+loct)
3456: cqg(lx1+loct)=cqg(lx0+loct)
3457: cqd(lx1+loct)=cqd(lx0+loct)
3458: c
3459: c check convergence
3460: c
3461: 700 if (initf.ne.3) go to 710
3462: if (ioff.ne.0) go to 750
3463: 710 if (icheck.eq.1) go to 720
3464: c tol=reltol*dmax1(dabs(cdhat),dabs(cdrain))+abstol
3465: c if (dabs(cdhat-cdrain).ge.tol) go to 720
3466: c tol=reltol*dmax1(dabs(cbhat),dabs(cbulk))+abstol
3467: c if (dabs(cbhat-cbulk).le.tol) go to 750
3468: tol=reltol*dabs(vgb)+vntol
3469: if(dabs(delvgb).ge.tol) go to 720
3470: tol=reltol*dabs(vbd)+vntol
3471: if(dabs(delvbd).ge.tol) go to 720
3472: tol=reltol*dabs(vbs)+vntol
3473: if(dabs(delvbs).lt.tol) go to 750
3474: 720 noncon=noncon+1
3475: 750 vbdo(lx0+loct)=vbd
3476: vbso(lx0+loct)=vbs
3477: vgbo(lx0+loct)=vgb
3478: cdo(lx0+loct)=cdrain
3479: cbo(lx0+loct)=cbulk
3480: gdgo(lx0+loct)=gccdg
3481: gddo(lx0+loct)=gccdd
3482: gdso(lx0+loct)=gccds
3483: gbgo(lx0+loct)=gccbg
3484: gbdo(lx0+loct)=gccbd
3485: gbso(lx0+loct)=gccbs
3486: c
3487: c load current vector
3488: c
3489: 900 ceqg=type*(cgate-gccgg*vgb+gccgd*vbd+gccgs*vbs)
3490: ceqb=type*(cbulk-gccbg*vgb+gccbd*vbd+gccbs*vbs)
3491: ceqd=type*(cdrain-gccdg*vgb+gccdd*vbd+gccds*vbs)
3492: value(lvn+node2)=value(lvn+node2)-ceqg
3493: value(lvn+node4)=value(lvn+node4)-ceqb
3494: value(lvn+node5)=value(lvn+node5)-ceqd
3495: value(lvn+node6)=value(lvn+node6)+ceqd+ceqg+ceqb
3496: c
3497: c load y matrix
3498: c
3499: locy=lynl+nodplc(loc+27)
3500: value(locy)=value(locy)+gdpr
3501: locy=lynl+nodplc(loc+28)
3502: value(locy)=value(locy)+gccgg
3503: locy=lynl+nodplc(loc+29)
3504: value(locy)=value(locy)+gspr
3505: locy=lynl+nodplc(loc+30)
3506: value(locy)=value(locy)-gccbg-gccbd-gccbs
3507: locy=lynl+nodplc(loc+31)
3508: value(locy)=value(locy)+gdpr+gccdd
3509: locy=lynl+nodplc(loc+32)
3510: value(locy)=value(locy)+gspr+gccss
3511: locy=lynl+nodplc(loc+10)
3512: value(locy)=value(locy)-gdpr
3513: locy=lynl+nodplc(loc+11)
3514: value(locy)=value(locy)-gccgg-gccgd-gccgs
3515: locy=lynl+nodplc(loc+12)
3516: value(locy)=value(locy)+gccgd
3517: locy=lynl+nodplc(loc+13)
3518: value(locy)=value(locy)+gccgs
3519: locy=lynl+nodplc(loc+14)
3520: value(locy)=value(locy)-gspr
3521: locy=lynl+nodplc(loc+15)
3522: value(locy)=value(locy)+gccbg
3523: locy=lynl+nodplc(loc+16)
3524: value(locy)=value(locy)+gccbd
3525: locy=lynl+nodplc(loc+17)
3526: value(locy)=value(locy)+gccbs
3527: locy=lynl+nodplc(loc+18)
3528: value(locy)=value(locy)-gdpr
3529: locy=lynl+nodplc(loc+19)
3530: value(locy)=value(locy)+gccdg
3531: locy=lynl+nodplc(loc+20)
3532: value(locy)=value(locy)-gccdg-gccdd-gccds
3533: locy=lynl+nodplc(loc+21)
3534: value(locy)=value(locy)+gccds
3535: locy=lynl+nodplc(loc+22)
3536: value(locy)=value(locy)+gccsg
3537: locy=lynl+nodplc(loc+23)
3538: value(locy)=value(locy)-gspr
3539: locy=lynl+nodplc(loc+24)
3540: value(locy)=value(locy)-gccsg-gccsd-gccss
3541: locy=lynl+nodplc(loc+25)
3542: value(locy)=value(locy)+gccsd
3543: 1000 loc=nodplc(loc)
3544: go to 10
3545: end
3546: subroutine calcq(vgb,vbd,vbs,qg,qc,qb,
3547: 1 ccgg,ccgd,ccgs,ccbg,ccbd,ccbs,
3548: 2 didvg,didvd,didvs)
3549: implicit double precision (a-h,o-z)
3550: common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet,
3551: 1 xmu,mode,modedc,icalc,initf,method,iord,maxord,noncon,iterno,
3552: 2 itemno,nosolv,ipostp,iscrch
3553: common /mosarg/ gamma,beta,vto,phi,cox,vbi,xnfs,xnsub,xd,xj,xl,
3554: 1 xlamda,utra,uexp,vbp,von,vdsat,theta,vcrit,vtra,gleff,cdrain
3555: common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok,
3556: 1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox
3557: iflag=1
3558: if(mode.ne.1) go to 5
3559: iflag=0
3560: if(modedc.eq.2.and.nosolv.ne.0) iflag=1
3561: if(initf.eq.4) iflag=1
3562: 5 vd=dmax1(phi-vbd,1.0d-8)
3563: vg=vgb-vbi+phi
3564: vs=dmax1(phi-vbs,1.0d-8)
3565: vsp5=dsqrt(vs)
3566: gammad=gamma
3567: if(gamma.eq.0.0d0) go to 7
3568: if(xj.eq.0.0d0) go to 7
3569: arg=dsqrt(1.0d0+xd*2.0d0*vsp5/xj)
3570: gfact=1.0d0-xj/xl*(arg-1.0d0)
3571: gfact=dmax1(0.5d0,gfact)
3572: gammad=gamma*gfact
3573: 7 vth=gammad*vsp5+vs
3574: c.. von is referenced to vgb for 'fetlim'
3575: c.. change mosfet to reference to vgs (von=vth+vbi-vs) for
3576: c.. printing
3577: von=vth+vbi-phi
3578: vdsat=0.0d0
3579: if(vg.lt.vth) go to 100
3580: c
3581: c 'on' region (linear and saturated)
3582: c
3583: gamma2=gammad*0.5d0
3584: sqarg=dsqrt(gamma2*gamma2+vg)
3585: vsat=(sqarg-gamma2)**2
3586: vsatcl=vsat
3587: vs2=vs*vs
3588: vs3=vs2*vs
3589: vs5=vs3*vs2
3590: vs1p5=vs*vsp5
3591: vs2p5=vs1p5*vs
3592: if(vcrit.eq.0.0d0) go to 9
3593: c...... iterate to new vsat
3594: iter=1
3595: 8 ve2=vsat*vsat
3596: c write(6,8878) iter,vsat
3597: 8878 format(' iter vsat ',i4,1pd11.2)
3598: vep5=dsqrt(vsat)
3599: ve1p5=vsat*vep5
3600: arg2=0.5d0*(ve2-vs2)
3601: arg1p5=gammad*(ve1p5-vs1p5)/1.5d0
3602: cdrain=vg*(vsat-vs)-arg1p5-arg2
3603: didve=vg-gammad*vep5-vsat
3604: d2idve=-0.5d0*gammad/dmax1(vep5,1.0d-5)-1.0d0
3605: if(vtra.eq.0.0d0) go to 88
3606: trafac=1.0d0/(1.0d0+(vsat-vs)/vtra)
3607: dtrdve=-trafac*trafac/vtra
3608: d2idve=d2idve*trafac+(dtrdve+dtrdve)*(didve-cdrain*trafac/vtra)
3609: didve=didve*trafac+dtrdve*cdrain
3610: cdrain=cdrain*trafac
3611: 88 delv=(didve*vcrit-cdrain)/dabs(didve-vcrit*d2idve)
3612: c.. limit voltage excursion to 1/2 old vsat
3613: if(dabs(delv).gt.0.5d0*vsat) delv=vsat*dsign(0.5d0,delv)
3614: vsat=vsat+delv
3615: c vsat=dmax1(vsat,1.0d-5)
3616: c vsat=dmin1(vsat,vsatcl)
3617: if(dabs(delv).lt.1.0d-6) go to 9
3618: iter=iter+1
3619: if(iter.gt.20) write(6,7777) vg,vs,vsat,delv
3620: 7777 format(' iteration count for vsat hit limit of 20'/,
3621: 1 ' vg vs vsat delv ',1p4d11.3)
3622: if(iter.gt.20) go to 9
3623: go to 8
3624: c.. end of iteration loop
3625: c.. vdsat is referenced to vds for printing only
3626: 9 vdsat=vsat-vs
3627: if(vsat.gt.vsatcl) write(6,9989) vsat,vsatcl
3628: 9989 format(' ********error****** vsat is larger than classical vsat',/
3629: 1' vsat ',1pd11.3,' classical vsat ',d11.3)
3630: 9999 format(' vsat ',1pd11.3,' classical vsat ',d11.3)
3631: if(vd.ge.vsat) go to 10
3632: c.. linear region
3633: ve=vd
3634: dvedvd=1.0d0
3635: dvedvg=0.0d0
3636: go to 15
3637: c.. saturated region
3638: 10 ve=vsat
3639: dvedvd=0.0d0
3640: c**************** zero dvedvg!!!
3641: c dvedvg=1.0d0-gamma2/sqarg
3642: dvedvg=0.0d0
3643: c
3644: 15 ve2=ve*ve
3645: ve3=ve2*ve
3646: ve5=ve3*ve2
3647: vep5=dsqrt(ve)
3648: ve1p5=ve*vep5
3649: ve2p5=ve1p5*ve
3650: arg2=0.5d0*(ve2-vs2)
3651: arg1p5=gammad*(ve1p5-vs1p5)/1.5d0
3652: cdrain=vg*(ve-vs)-arg1p5-arg2
3653: didve=vg-gammad*vep5-ve
3654: didvg=ve-vs+didve*dvedvg
3655: didvs=-vg+gammad*vsp5+vs
3656: if(iflag.eq.0) go to 30
3657: if(dabs(cdrain).gt.1.0d-5) go to 20
3658: c .. special case when ve almost equals vs and regular formulas don't work
3659: c write(6,5475) time,cdrain
3660: 5475 format(' time = ',1pd15.6,' cdrain = ',e11.3)
3661: qg=cox*(vg-vs)
3662: ccgg=cox
3663: ccgd=-0.5d0*cox
3664: ccgs=ccgd
3665: qb=-cox*gammad*vsp5
3666: ccbg=0.0d0
3667: ccbd=-cox*0.25d0*gammad/dmax1(vsp5,1.0d-2)
3668: ccbs=ccbd
3669: go to 30
3670: c
3671: 20 arg2p5=gammad*0.4d0*(ve2p5-vs2p5)
3672: varg=(vg*arg2-arg2p5-(ve3-vs3)/3.0d0)/cdrain
3673: qg=cox*(vg-varg)
3674: dqgdve=cox/cdrain*(varg-ve)*didve
3675: ccgg=cox*(1.0d0-(arg2-varg*(ve-vs))/cdrain)
3676: 1 +dqgdve*dvedvg
3677: ccgd=dqgdve*dvedvd
3678: ccgs=cox/cdrain*(varg-vs)*didvs
3679: qb=-cox/cdrain*(vg*arg1p5-gammad*gammad*arg2-arg2p5)
3680: dqbdve=-cox/cdrain*(gammad*vep5+qb/cox)*didve
3681: ccbd=dqbdve*dvedvd
3682: ccbs=-cox/cdrain*(gammad*vsp5+qb/cox)*didvs
3683: ccbg=-cox/cdrain*(arg1p5+qb/cox*(ve-vs))
3684: 1 +dqbdve*dvedvg
3685: c.. mobility factor (a-la bdm)
3686: 30 if(uexp.eq.0.0d0) go to 35
3687: vdenom=vg-vth-utra*(ve-vs)
3688: if(vdenom.le.vbp) go to 45
3689: arg=vbp/vdenom
3690: ufact=dexp(uexp*dlog(arg))
3691: dcoef=-uexp*ufact*arg/vbp
3692: didvg=ufact*didvg+cdrain*dcoef
3693: didvs=ufact*didvs-cdrain*dcoef*(0.5d0*gammad/vsp5+1.0d0-utra)
3694: didve=ufact*didve-cdrain*dcoef*utra
3695: cdrain=cdrain*ufact
3696: go to 45
3697: c.. lateral field effects
3698: 35 if(vtra.eq.0.0d0) go to 40
3699: trafac=1.0d0/(1.0d0+(ve-vs)/vtra)
3700: dtrdve=-trafac*trafac/vtra
3701: didve=didve*trafac+dtrdve*cdrain
3702: c.. note that dtrdvs=-dtrdve
3703: didvs=didvs*trafac-dtrdve*cdrain
3704: didvg=didvg*trafac
3705: cdrain=cdrain*trafac
3706: c.. mobility variation a-la sun-daseking
3707: 40 if(theta.eq.0.0d0) go to 45
3708: ufact=1.0d0/(1.0d0+theta*(vg-vth))
3709: dufact=-theta*ufact*ufact
3710: didve=ufact*didve
3711: didvg=ufact*didvg+cdrain*dufact
3712: didvs=ufact*didvs-cdrain*dufact*(0.5d0*gammad/vsp5+1.0d0)
3713: cdrain=cdrain*ufact
3714: c .. done with 've', use it
3715: 45 didvd=didve*dvedvd
3716: c.. channel length modulation
3717: if(vcrit.ne.0.0d0) go to 80
3718: if (xlamda.gt.0.0d0) go to 50
3719: if (xnsub.eq.0.0d0) go to 50
3720: c.. frohman-grove (lousy) formulation modified a-la newton
3721: arg1=(vd-vsat)/4.0d0
3722: arg2=dsqrt(1.0d0+arg1*arg1)
3723: arg3=dsqrt(arg1+arg2)
3724: clfact=1.0d0/(1.0d0-xd/xl*arg3)
3725: if(clfact.le.0.0d0) go to 60
3726: dclfct=0.125d0*clfact*clfact*xd/xl*(1.0d0+arg1/arg2)/arg3
3727: didvd=clfact*didvd+cdrain*dclfct
3728: didvg=clfact*didvg-cdrain*dclfct*(1.0d0-gamma2/sqarg)
3729: didvs=clfact*didvs
3730: cdrain=cdrain*clfact
3731: go to 200
3732: c.. simple (1+vds*lambda/l) formulation
3733: 50 xlfact=xlamda/xl
3734: clfact=1.0d0+xlfact*(vd-vs)
3735: didvd=clfact*didvd+cdrain*xlfact
3736: didvs=clfact*didvs-cdrain*xlfact
3737: didvg=clfact*didvg
3738: cdrain=cdrain*clfact
3739: go to 200
3740: c.. device punched thru
3741: 60 clfact=1000.0d0
3742: if(ipunch.gt.50) go to 200
3743: ipunch=ipunch+1
3744: write(6,61)
3745: 61 format('0warning: channel length reduced to zero in mosfet')
3746: go to 200
3747: c.. into saturation with vcrit ne 0
3748: 80 if(vd.le.vsat) go to 200
3749: xk1=vcrit/2.0d0/xl/gleff
3750: temp=dsqrt(xk1*xk1+(vd-vsat)/gleff)
3751: clfact=1.0d0+(temp-xk1)/xl
3752: dclfct=0.5d0/xl/temp/gleff
3753: didvd=didvd*clfact+cdrain*dclfct
3754: didvs=didvs*clfact
3755: didvg=didvg*clfact
3756: cdrain=cdrain*clfact
3757: c
3758: go to 200
3759: c
3760: c.. cut-off region (vg<vth)
3761: c
3762: 100 continue
3763: cdrain=0.0d0
3764: didvg=0.0d0
3765: didvd=0.0d0
3766: didvs=0.0d0
3767: if(iflag.eq.0) return
3768: if(vg.gt.0.0d0) go to 120
3769: qg=cox*vg
3770: ccgg=cox
3771: go to 130
3772: 120 gamma2=gammad*0.5d0
3773: sqarg=dsqrt(gamma2*gamma2+vg)
3774: qg=gammad*cox*(sqarg-gamma2)
3775: ccgg=0.5d0*cox*gammad/sqarg
3776: 130 qb=-qg
3777: ccbg=-ccgg
3778: ccgd=0.0d0
3779: ccgs=0.0d0
3780: ccbd=0.0d0
3781: ccbs=0.0d0
3782: 200 qc=-(qg+qb)
3783: c write(6,7657) time,vg,vs,ve,qg,ccgg,ccgd,ccgs,qb,ccbg,ccbd,ccbs
3784: 7657 format(' time = ',1pd12.5,' vg vs ve ',3d11.3,
3785: 1 /,' qg ',4d11.3,' qb ',4d11.3)
3786: return
3787: end
3788: subroutine gasfet(loc)
3789: c *** a gasfet (or any other) model may ***
3790: c * be inserted here... if you happen *
3791: c * to have a good one! *
3792: c *** ***
3793: c
3794: return
3795: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.