Commit | Line | Data |
---|---|---|
7316c58a D |
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 |