1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 Author: 1985 Thomas L. Quarles
4 Modified: 2000  AlansFixes
5 **********/
6 
7 /* subroutine to do DC TRANSIENT analysis
8         --- ONLY, unlike spice2 routine with the same name! */
9 
10 #include "ngspice/ngspice.h"
11 #include "ngspice/cktdefs.h"
12 #include "cktaccept.h"
13 #include "ngspice/trandefs.h"
14 #include "ngspice/sperror.h"
15 #include "ngspice/fteext.h"
16 #include "ngspice/missing_math.h"
17 
18 /* for setting breakpoints required by dbs data base */
19 extern struct dbcomm *dbs;
20 #include "ngspice/ftedebug.h"
21 
22 #ifdef XSPICE
23 /* gtri - add - wbk - Add headers */
24 #include "ngspice/miftypes.h"
25 
26 #include "ngspice/evt.h"
27 #include "ngspice/enh.h"
28 #include "ngspice/mif.h"
29 #include "ngspice/evtproto.h"
30 #include "ngspice/ipctiein.h"
31 /* gtri - end - wbk - Add headers */
32 #endif
33 
34 #ifdef CLUSTER
35 #include "ngspice/cluster.h"
36 #endif
37 
38 #ifdef SHARED_MODULE
39 extern int add_bkpt(void);
40 extern int sharedsync(double*, double*, double, double, double, int, int*, int);
41 extern int ng_ident;      /* for debugging */
42 #endif
43 
44 #define INIT_STATS() \
45 do { \
46     startTime = SPfrontEnd->IFseconds();        \
47     startIters = ckt->CKTstat->STATnumIter;     \
48     startdTime = ckt->CKTstat->STATdecompTime;  \
49     startsTime = ckt->CKTstat->STATsolveTime;   \
50     startlTime = ckt->CKTstat->STATloadTime;    \
51     startkTime = ckt->CKTstat->STATsyncTime;    \
52 } while(0)
53 
54 #define UPDATE_STATS(analysis) \
55 do { \
56     ckt->CKTcurrentAnalysis = analysis; \
57     ckt->CKTstat->STATtranTime += SPfrontEnd->IFseconds() - startTime; \
58     ckt->CKTstat->STATtranIter += ckt->CKTstat->STATnumIter - startIters; \
59     ckt->CKTstat->STATtranDecompTime += ckt->CKTstat->STATdecompTime - startdTime; \
60     ckt->CKTstat->STATtranSolveTime += ckt->CKTstat->STATsolveTime - startsTime; \
61     ckt->CKTstat->STATtranLoadTime += ckt->CKTstat->STATloadTime - startlTime; \
62     ckt->CKTstat->STATtranSyncTime += ckt->CKTstat->STATsyncTime - startkTime; \
63 } while(0)
64 
65 
66 int
DCtran(CKTcircuit * ckt,int restart)67 DCtran(CKTcircuit *ckt,
68        int restart)   /* forced restart flag */
69 {
70     TRANan *job = (TRANan *) ckt->CKTcurJob;
71 
72     int i;
73     double olddelta;
74     double delta;
75     double newdelta;
76     double *temp;
77     double startdTime;
78     double startsTime;
79     double startlTime;
80     double startkTime;
81     double startTime;
82     int startIters;
83     int converged;
84     int firsttime;
85     int error;
86 #ifdef WANT_SENSE2
87     int save, save2, size;
88     long save1;
89 #endif
90     int save_order;
91     long save_mode;
92     IFuid timeUid;
93     IFuid *nameList;
94     int numNames;
95     double maxstepsize = 0.0;
96 
97     int ltra_num;
98     CKTnode *node;
99 #ifdef XSPICE
100 /* gtri - add - wbk - 12/19/90 - Add IPC stuff */
101     Ipc_Boolean_t  ipc_firsttime = IPC_TRUE;
102     Ipc_Boolean_t  ipc_secondtime = IPC_FALSE;
103     Ipc_Boolean_t  ipc_delta_cut = IPC_FALSE;
104     double         ipc_last_time = 0.0;
105     double         ipc_last_delta = 0.0;
106 /* gtri - end - wbk - 12/19/90 - Add IPC stuff */
107 #endif
108 #if defined CLUSTER || defined SHARED_MODULE
109     int redostep;
110 #endif
111     if(restart || ckt->CKTtime == 0) {
112         delta=MIN(ckt->CKTfinalTime/100,ckt->CKTstep)/10;
113 
114 #ifdef STEPDEBUG
115         printf("delta = %g    finalTime/100: %g    CKTstep: %g\n",delta,ckt->CKTfinalTime/100,ckt->CKTstep);
116 #endif
117         /* begin LTRA code addition */
118         if (ckt->CKTtimePoints != NULL)
119             FREE(ckt->CKTtimePoints);
120 
121         if (ckt->CKTstep >= ckt->CKTmaxStep)
122             maxstepsize = ckt->CKTstep;
123         else
124             maxstepsize = ckt->CKTmaxStep;
125 
126         ckt->CKTsizeIncr = 10;
127         ckt->CKTtimeIndex = -1; /* before the DC soln has been stored */
128         ckt->CKTtimeListSize = (int) ceil( ckt->CKTfinalTime / maxstepsize );
129         ltra_num = CKTtypelook("LTRA");
130         if (ltra_num >= 0 && ckt->CKThead[ltra_num] != NULL)
131             ckt->CKTtimePoints = TMALLOC(double, ckt->CKTtimeListSize);
132         /* end LTRA code addition */
133 
134         if(ckt->CKTbreaks) FREE(ckt->CKTbreaks);
135         ckt->CKTbreaks = TMALLOC(double, 2);
136         if(ckt->CKTbreaks == NULL) return(E_NOMEM);
137         ckt->CKTbreaks[0] = 0;
138         ckt->CKTbreaks[1] = ckt->CKTfinalTime;
139         ckt->CKTbreakSize = 2;
140 
141 #ifdef SHARED_MODULE
142         add_bkpt();
143 #endif
144 
145 #ifdef XSPICE
146 /* gtri - begin - wbk - 12/19/90 - Modify setting of CKTminBreak */
147         /* Set to 10 times delmin for ATESSE 1 compatibity */
148         if(ckt->CKTminBreak==0) ckt->CKTminBreak = 10.0 * ckt->CKTdelmin;
149 /* gtri - end - wbk - 12/19/90 - Modify setting of CKTminBreak */
150 #else
151         if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5;
152 #endif
153 
154 #ifdef XSPICE
155 /* gtri - add - wbk - 12/19/90 - Add IPC stuff and set anal_init and anal_type */
156         /* Tell the beginPlot routine what mode we're in */
157         g_ipc.anal_type = IPC_ANAL_TRAN;
158 
159         /* Tell the code models what mode we're in */
160         g_mif_info.circuit.anal_type = MIF_DC;
161 
162         g_mif_info.circuit.anal_init = MIF_TRUE;
163 /* gtri - end - wbk */
164 #endif
165         error = CKTnames(ckt,&numNames,&nameList);
166         if(error) return(error);
167         SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, "time", UID_OTHER, NULL);
168         error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
169                                            ckt->CKTcurJob->JOBname,
170                                            timeUid, IF_REAL,
171                                            numNames, nameList, IF_REAL,
172                                            &(job->TRANplot));
173         tfree(nameList);
174         if(error) return(error);
175 
176         /* initialize CKTsoaCheck `warn' counters */
177         if (ckt->CKTsoaCheck)
178             error = CKTsoaInit();
179 
180         ckt->CKTtime = 0;
181         ckt->CKTdelta = 0;
182         ckt->CKTbreak = 1;
183         firsttime = 1;
184         save_mode = (ckt->CKTmode&MODEUIC) | MODETRANOP | MODEINITJCT;
185         save_order = ckt->CKTorder;
186 
187 /* Add breakpoints here which have been requested by the user setting the
188    stop command as 'stop when time = xx'.
189    Get data from the global dbs data base.
190 */
191         if (dbs) {
192             struct dbcomm *d;
193             for (d = dbs; d; d = d->db_next)
194                 if ((d->db_type == DB_STOPWHEN) && cieq(d->db_nodename1,"time")
195                     && (d->db_value2 > 0)) {
196                     CKTsetBreak(ckt, d->db_value2);
197                     if (ft_ngdebug)
198                         printf("breakpoint set to time = %g\n", d->db_value2);
199                 }
200         }
201 
202 #ifdef XSPICE
203 /* gtri - begin - wbk - set a breakpoint at end of supply ramping time */
204         /* must do this after CKTtime set to 0 above */
205         if(ckt->enh->ramp.ramptime > 0.0)
206             CKTsetBreak(ckt, ckt->enh->ramp.ramptime);
207 /* gtri - end - wbk - set a breakpoint at end of supply ramping time */
208 
209 /* gtri - begin - wbk - Call EVTop if event-driven instances exist */
210         if(ckt->evt->counts.num_insts != 0) {
211             /* use new DCOP algorithm */
212             converged = EVTop(ckt,
213                         (ckt->CKTmode & MODEUIC) | MODETRANOP | MODEINITJCT,
214                         (ckt->CKTmode & MODEUIC) | MODETRANOP | MODEINITFLOAT,
215                         ckt->CKTdcMaxIter,
216                         MIF_TRUE);
217             EVTdump(ckt, IPC_ANAL_DCOP, 0.0);
218 
219             EVTop_save(ckt, MIF_FALSE, 0.0);
220 
221 /* gtri - end - wbk - Call EVTop if event-driven instances exist */
222         } else
223 #endif
224             converged = CKTop(ckt,
225                 (ckt->CKTmode & MODEUIC) | MODETRANOP | MODEINITJCT,
226                 (ckt->CKTmode & MODEUIC) | MODETRANOP | MODEINITFLOAT,
227                 ckt->CKTdcMaxIter);
228 
229         if(converged != 0) {
230             fprintf(stdout,"\nTransient solution failed -\n");
231             CKTncDump(ckt);
232             fprintf(stdout,"\n");
233             fflush(stdout);
234         } else if (ckt->CKTmode & MODEUIC) {
235             fprintf(stdout,"Using transient initial conditions\n");
236             fflush(stdout);
237         } else if (!ft_noacctprint && !ft_noinitprint) {
238             fprintf(stdout,"\nInitial Transient Solution\n");
239             fprintf(stdout,"--------------------------\n\n");
240             fprintf(stdout,"%-30s %15s\n", "Node", "Voltage");
241             fprintf(stdout,"%-30s %15s\n", "----", "-------");
242             for(node=ckt->CKTnodes->next;node;node=node->next) {
243                 if (strstr(node->name, "#branch") || !strchr(node->name, '#'))
244                     fprintf(stdout,"%-30s %15g\n", node->name,
245                                               ckt->CKTrhsOld[node->number]);
246             }
247             fprintf(stdout,"\n");
248             fflush(stdout);
249         }
250 
251         if (converged != 0) {
252             SPfrontEnd->OUTendPlot(job->TRANplot);
253             return(converged);
254         }
255 #ifdef XSPICE
256 /* gtri - add - wbk - 12/19/90 - Add IPC stuff */
257 
258         /* Send the operating point results for Mspice compatibility */
259         if(g_ipc.enabled) {
260             ipc_send_dcop_prefix();
261             CKTdump(ckt, 0.0, job->TRANplot);
262             ipc_send_dcop_suffix();
263         }
264 
265 /* gtri - end - wbk */
266 
267 /* gtri - add - wbk - 12/19/90 - set anal_init and anal_type */
268 
269         g_mif_info.circuit.anal_init = MIF_TRUE;
270 
271         /* Tell the code models what mode we're in */
272         g_mif_info.circuit.anal_type = MIF_TRAN;
273 
274 /* gtri - end - wbk */
275 
276 /* gtri - begin - wbk - Add Breakpoint stuff */
277 
278         /* Initialize the temporary breakpoint variables to infinity */
279         g_mif_info.breakpoint.current = 1.0e30;
280         g_mif_info.breakpoint.last    = 1.0e30;
281 
282 /* gtri - end - wbk - Add Breakpoint stuff */
283 #endif
284         ckt->CKTstat->STATtimePts ++;
285         ckt->CKTorder = 1;
286         for(i=0;i<7;i++) {
287             ckt->CKTdeltaOld[i]=ckt->CKTmaxStep;
288         }
289         ckt->CKTdelta = delta;
290 #ifdef STEPDEBUG
291         (void)printf("delta initialized to %g\n",ckt->CKTdelta);
292 #endif
293         ckt->CKTsaveDelta = ckt->CKTfinalTime/50;
294 
295 #ifdef WANT_SENSE2
296         if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){
297 #ifdef SENSDEBUG
298             printf("\nTransient Sensitivity Results\n\n");
299             CKTsenPrint(ckt);
300 #endif /* SENSDEBUG */
301             save = ckt->CKTsenInfo->SENmode;
302             ckt->CKTsenInfo->SENmode = TRANSEN;
303             save1 = ckt->CKTmode;
304             save2 = ckt->CKTorder;
305             ckt->CKTmode = save_mode;
306             ckt->CKTorder = save_order;
307             error = CKTsenDCtran(ckt);
308             if (error)
309                 return(error);
310 
311             ckt->CKTmode = save1;
312             ckt->CKTorder = save2;
313         }
314 #endif
315 
316         ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODETRAN | MODEINITTRAN;
317         /* modeinittran set here */
318         ckt->CKTag[0]=ckt->CKTag[1]=0;
319         memcpy(ckt->CKTstate1, ckt->CKTstate0,
320               (size_t) ckt->CKTnumStates * sizeof(double));
321 
322 #ifdef WANT_SENSE2
323         if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){
324             size = SMPmatSize(ckt->CKTmatrix);
325             for(i = 1; i<=size ; i++)
326                 ckt->CKTrhsOp[i] = ckt->CKTrhsOld[i];
327         }
328 #endif
329 
330         INIT_STATS();
331 #ifdef CLUSTER
332         CLUsetup(ckt);
333 #endif
334     } else {
335         /* saj As traninit resets CKTmode */
336         ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODETRAN | MODEINITPRED;
337         /* saj */
338         INIT_STATS();
339         if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5;
340         firsttime=0;
341         /* To get rawfile working saj*/
342         error = SPfrontEnd->OUTpBeginPlot (NULL, NULL,
343                                            NULL,
344                                            NULL, 0,
345                                            666, NULL, 666,
346                                            &(job->TRANplot));
347         if(error) {
348             fprintf(stderr, "Couldn't relink rawfile\n");
349             return error;
350         }
351         /* end saj*/
352         goto resume;
353     }
354 
355 /* 650 */
356     nextTime:
357 
358     /* begin LTRA code addition */
359     if (ckt->CKTtimePoints) {
360     ckt->CKTtimeIndex++;
361         if (ckt->CKTtimeIndex >= ckt->CKTtimeListSize) {
362             /* need more space */
363             int need;
364             need = (int) ceil( (ckt->CKTfinalTime - ckt->CKTtime) / maxstepsize );
365             if (need < ckt->CKTsizeIncr)
366                 need = ckt->CKTsizeIncr;
367             ckt->CKTtimeListSize += need;
368             ckt->CKTtimePoints = TREALLOC(double, ckt->CKTtimePoints, ckt->CKTtimeListSize);
369             ckt->CKTsizeIncr = (int) ceil(1.4 * ckt->CKTsizeIncr);
370         }
371         ckt->CKTtimePoints[ckt->CKTtimeIndex] = ckt->CKTtime;
372     }
373     /* end LTRA code addition */
374 
375     error = CKTaccept(ckt);
376     /* check if current breakpoint is outdated; if so, clear */
377     if (ckt->CKTtime > ckt->CKTbreaks[0]) CKTclrBreak(ckt);
378 
379     if (ckt->CKTsoaCheck)
380         error = CKTsoaCheck(ckt);
381 
382     /*
383  * Breakpoint handling scheme:
384  * When a timepoint t is accepted (by CKTaccept), clear all previous
385  * breakpoints, because they will never be needed again.
386  *
387  * t may itself be a breakpoint, or indistinguishably close. DON'T
388  * clear t itself; recognise it as a breakpoint and act accordingly
389  *
390  * if t is not a breakpoint, limit the timestep so that the next
391  * breakpoint is not crossed
392  */
393 
394 #ifdef STEPDEBUG
395     printf("Delta %g accepted at time %g (finaltime: %g)\n",ckt->CKTdelta,ckt->CKTtime,ckt->CKTfinalTime);
396     fflush(stdout);
397 #endif /* STEPDEBUG */
398     ckt->CKTstat->STATaccepted ++;
399     ckt->CKTbreak = 0;
400     /* XXX Error will cause single process to bail. */
401     if(error)  {
402         UPDATE_STATS(DOING_TRAN);
403         return(error);
404     }
405 #ifdef XSPICE
406 /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
407 
408     if ((g_ipc.enabled) || wantevtdata) {
409 
410         /* Send event-driven results */
411         EVTdump(ckt, IPC_ANAL_TRAN, 0.0);
412 
413         /* Then follow with analog results... */
414 
415         /* Test to see if delta was cut by a breakpoint, */
416         /* a non-convergence, or a too large truncation error */
417         if(ipc_firsttime)
418             ipc_delta_cut = IPC_FALSE;
419         else if(ckt->CKTtime < (ipc_last_time + (0.999 * ipc_last_delta)))
420             ipc_delta_cut = IPC_TRUE;
421         else
422             ipc_delta_cut = IPC_FALSE;
423 
424         /* Record the data required to check for delta cuts */
425         ipc_last_time = ckt->CKTtime;
426         ipc_last_delta = MIN(ckt->CKTdelta, ckt->CKTmaxStep);
427 
428         /* Send results data if time since last dump is greater */
429         /* than 'mintime', or if first or second timepoints, */
430         /* or if delta was cut */
431         if( (ckt->CKTtime >= (g_ipc.mintime + g_ipc.last_time)) ||
432             ipc_firsttime || ipc_secondtime || ipc_delta_cut ) {
433 
434             if (wantevtdata)
435                 CKTdump(ckt, ckt->CKTtime, job->TRANplot);
436             else {
437                 ipc_send_data_prefix(ckt->CKTtime);
438                 CKTdump(ckt, ckt->CKTtime, job->TRANplot);
439                 ipc_send_data_suffix();
440             }
441 
442             if(ipc_firsttime) {
443                 ipc_firsttime = IPC_FALSE;
444                 ipc_secondtime = IPC_TRUE;
445             } else if(ipc_secondtime) {
446                 ipc_secondtime = IPC_FALSE;
447             }
448 
449             g_ipc.last_time = ckt->CKTtime;
450         }
451     } else
452 /* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
453 #endif
454 #ifdef CLUSTER
455         CLUoutput(ckt);
456 #endif
457         if((ckt->CKTmode&MODEUIC && ckt->CKTtime > 0 && ckt->CKTtime >= ckt->CKTinitTime)
458                 || (!(ckt->CKTmode&MODEUIC) && ckt->CKTtime >= ckt->CKTinitTime))
459             CKTdump(ckt, ckt->CKTtime, job->TRANplot);
460 #ifdef XSPICE
461 /* gtri - begin - wbk - Update event queues/data for accepted timepoint */
462     /* Note: this must be done AFTER sending results to SI so it can't */
463     /* go next to CKTaccept() above */
464     if(ckt->evt->counts.num_insts > 0)
465         EVTaccept(ckt, ckt->CKTtime);
466 /* gtri - end - wbk - Update event queues/data for accepted timepoint */
467 #endif
468     ckt->CKTstat->STAToldIter = ckt->CKTstat->STATnumIter;
469     if(check_autostop("tran") ||
470       fabs(ckt->CKTtime - ckt->CKTfinalTime) < ckt->CKTminBreak ||
471       AlmostEqualUlps( ckt->CKTtime, ckt->CKTfinalTime, 100 ) ) {
472 #ifdef STEPDEBUG
473         printf(" done:  time is %g, final time is %g, and tol is %g\n",
474         ckt->CKTtime, ckt->CKTfinalTime, ckt->CKTminBreak);
475 #endif
476         SPfrontEnd->OUTendPlot (job->TRANplot);
477         job->TRANplot = NULL;
478         UPDATE_STATS(0);
479 #ifdef WANT_SENSE2
480         if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){
481             ckt->CKTsenInfo->SENmode = save;
482         }
483 #endif
484         return(OK);
485     }
486     if(SPfrontEnd->IFpauseTest()) {
487         /* user requested pause... */
488         UPDATE_STATS(DOING_TRAN);
489         return(E_PAUSE);
490     }
491 resume:
492 #ifdef STEPDEBUG
493     if( (ckt->CKTdelta <= ckt->CKTfinalTime/50) &&
494         (ckt->CKTdelta <= ckt->CKTmaxStep)) {
495         ;
496     } else {
497         if(ckt->CKTfinalTime/50<ckt->CKTmaxStep) {
498             (void)printf("limited by Tstop/50\n");
499         } else {
500             (void)printf("limited by Tmax == %g\n",ckt->CKTmaxStep);
501         }
502     }
503 #endif
504 #ifdef HAS_PROGREP
505     if (ckt->CKTtime == 0.)
506         SetAnalyse( "tran init", 0);
507     else
508         SetAnalyse( "tran", (int)((ckt->CKTtime * 1000.) / ckt->CKTfinalTime + 0.5));
509 #endif
510     ckt->CKTdelta =
511             MIN(ckt->CKTdelta,ckt->CKTmaxStep);
512 #ifdef XSPICE
513 /* gtri - begin - wbk - Cut integration order if first timepoint after breakpoint */
514     /* if(ckt->CKTtime == g_mif_info.breakpoint.last) */
515     if ( AlmostEqualUlps( ckt->CKTtime, g_mif_info.breakpoint.last, 100 ) )
516         ckt->CKTorder = 1;
517 /* gtri - end   - wbk - Cut integration order if first timepoint after breakpoint */
518 
519 #endif
520 
521   /* are we at a breakpoint, or indistinguishably close? */
522     /* if ((ckt->CKTtime == ckt->CKTbreaks[0]) || (ckt->CKTbreaks[0] - */
523     if ( AlmostEqualUlps( ckt->CKTtime, ckt->CKTbreaks[0], 100 ) ||
524          ckt->CKTbreaks[0] - ckt->CKTtime <= ckt->CKTdelmin) {
525         /* first timepoint after a breakpoint - cut integration order */
526         /* and limit timestep to .1 times minimum of time to next breakpoint,
527          * and previous timestep
528          */
529         ckt->CKTorder = 1;
530 #ifdef STEPDEBUG
531         if( (ckt->CKTdelta > .1*ckt->CKTsaveDelta) ||
532             (ckt->CKTdelta > .1*(ckt->CKTbreaks[1] - ckt->CKTbreaks[0])) ) {
533             if(ckt->CKTsaveDelta < (ckt->CKTbreaks[1] - ckt->CKTbreaks[0]))  {
534                 (void)printf("limited by pre-breakpoint delta (saveDelta: %g, nxt_breakpt: %g, curr_breakpt: %g\n",
535                   ckt->CKTsaveDelta, ckt->CKTbreaks[1], ckt->CKTbreaks[0]);
536             } else {
537                 (void)printf("limited by next breakpoint\n");
538             }
539         }
540 #endif
541 
542         ckt->CKTdelta = MIN(ckt->CKTdelta, .1 * MIN(ckt->CKTsaveDelta,
543             ckt->CKTbreaks[1] - ckt->CKTbreaks[0]));
544 
545         if(firsttime) {
546             /* set a breakpoint to reduce ringing of current in devices */
547             if (ckt->CKTmode & MODEUIC)
548                 CKTsetBreak(ckt, ckt->CKTstep);
549 
550             ckt->CKTdelta /= 10;
551 #ifdef STEPDEBUG
552             (void)printf("delta cut for initial timepoint\n");
553 #endif
554         }
555 
556 #ifndef XSPICE
557         /* don't want to get below delmin for no reason */
558         ckt->CKTdelta = MAX(ckt->CKTdelta, ckt->CKTdelmin*2.0);
559 #endif
560 
561     }
562 
563 #ifndef XSPICE
564     else if(ckt->CKTtime + ckt->CKTdelta >= ckt->CKTbreaks[0]) {
565         ckt->CKTsaveDelta = ckt->CKTdelta;
566         ckt->CKTdelta = ckt->CKTbreaks[0] - ckt->CKTtime;
567 #ifdef STEPDEBUG
568         (void)printf("delta cut to %g to hit breakpoint\n",ckt->CKTdelta);
569         fflush(stdout);
570 #endif
571         ckt->CKTbreak = 1; /* why? the current pt. is not a bkpt. */
572     }
573 #endif /* !XSPICE */
574 
575 
576 #ifdef XSPICE
577 /* gtri - begin - wbk - Add Breakpoint stuff */
578 
579     if(ckt->CKTtime + ckt->CKTdelta >= g_mif_info.breakpoint.current) {
580         /* If next time > temporary breakpoint, force it to the breakpoint */
581         /* And mark that timestep was set by temporary breakpoint */
582         ckt->CKTsaveDelta = ckt->CKTdelta;
583         ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime;
584         g_mif_info.breakpoint.last = ckt->CKTtime + ckt->CKTdelta;
585     } else {
586         /* Else, mark that timestep was not set by temporary breakpoint */
587         g_mif_info.breakpoint.last = 1.0e30;
588     }
589 
590 /* gtri - end - wbk - Add Breakpoint stuff */
591 
592 /* gtri - begin - wbk - Modify Breakpoint stuff */
593     /* Throw out any permanent breakpoint times <= current time */
594     for (;;) {
595 #ifdef STEPDEBUG
596         printf("    brk_pt: %g    ckt_time: %g    ckt_min_break: %g\n",ckt->CKTbreaks[0], ckt->CKTtime, ckt->CKTminBreak);
597 #endif
598         if(AlmostEqualUlps(ckt->CKTbreaks[0], ckt->CKTtime, 100) ||
599            ckt->CKTbreaks[0] <= ckt->CKTtime + ckt->CKTminBreak) {
600 #ifdef STEPDEBUG
601             printf("throwing out permanent breakpoint times <= current time (brk pt: %g)\n",ckt->CKTbreaks[0]);
602             printf("    ckt_time: %g    ckt_min_break: %g\n",ckt->CKTtime, ckt->CKTminBreak);
603 #endif
604             CKTclrBreak(ckt);
605         } else {
606             break;
607         }
608     }
609     /* Force the breakpoint if appropriate */
610     if(ckt->CKTtime + ckt->CKTdelta > ckt->CKTbreaks[0]) {
611         ckt->CKTbreak = 1;
612         ckt->CKTsaveDelta = ckt->CKTdelta;
613         ckt->CKTdelta = ckt->CKTbreaks[0] - ckt->CKTtime;
614     }
615 
616 /* gtri - end - wbk - Modify Breakpoint stuff */
617 
618 #ifdef SHARED_MODULE
619         /* Either directly go to next time step, or modify ckt->CKTdelta depending on
620            synchronization requirements. sharedsync() returns 0. */
621     sharedsync(&ckt->CKTtime, &ckt->CKTdelta, 0, ckt->CKTfinalTime,
622         ckt->CKTdelmin, 0, &ckt->CKTstat->STATrejected, 0);
623 #endif
624 
625 /* gtri - begin - wbk - Do event solution */
626 
627     if(ckt->evt->counts.num_insts > 0) {
628 
629         /* if time = 0 and op_alternate was specified as false during */
630         /* dcop analysis, call any changed instances to let them */
631         /* post their outputs with their associated delays */
632         if((ckt->CKTtime == 0.0) && (! ckt->evt->options.op_alternate))
633             EVTiter(ckt);
634 
635         /* while there are events on the queue with event time <= next */
636         /* projected analog time, process them */
637         while((g_mif_info.circuit.evt_step = EVTnext_time(ckt))
638                <= (ckt->CKTtime + ckt->CKTdelta)) {
639 
640             /* Initialize temp analog bkpt to infinity */
641             g_mif_info.breakpoint.current = 1e30;
642 
643             /* Pull items off queue and process them */
644             EVTdequeue(ckt, g_mif_info.circuit.evt_step);
645             EVTiter(ckt);
646 
647             /* If any instances have forced an earlier */
648             /* next analog time, cut the delta */
649             if(ckt->CKTbreaks[0] < g_mif_info.breakpoint.current)
650                 if(ckt->CKTbreaks[0] > ckt->CKTtime + ckt->CKTminBreak)
651                     g_mif_info.breakpoint.current = ckt->CKTbreaks[0];
652             if(g_mif_info.breakpoint.current < ckt->CKTtime + ckt->CKTdelta) {
653                 /* Breakpoint must be > last accepted timepoint */
654                 /* and >= current event time */
655                 if(g_mif_info.breakpoint.current >  ckt->CKTtime + ckt->CKTminBreak  &&
656                    g_mif_info.breakpoint.current >= g_mif_info.circuit.evt_step) {
657                     ckt->CKTsaveDelta = ckt->CKTdelta;
658                     ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime;
659                     g_mif_info.breakpoint.last = ckt->CKTtime + ckt->CKTdelta;
660                 }
661             }
662 
663         } /* end while next event time <= next analog time */
664     } /* end if there are event instances */
665 
666 /* gtri - end - wbk - Do event solution */
667 #else
668 
669 #ifdef CLUSTER
670     if(!CLUsync(ckt->CKTtime,&ckt->CKTdelta,0)) {
671       printf("Sync error!\n");
672       exit(0);
673     }
674 #endif /* CLUSTER */
675 
676 #ifdef SHARED_MODULE
677     /* Either directly go to next time step, or modify ckt->CKTdelta depending on
678        synchronization requirements. sharedsync() returns 0.
679     */
680     sharedsync(&ckt->CKTtime, &ckt->CKTdelta, 0, ckt->CKTfinalTime,
681         ckt->CKTdelmin, 0, &ckt->CKTstat->STATrejected, 0);
682 #endif
683 
684 #endif
685     for(i=5; i>=0; i--)
686         ckt->CKTdeltaOld[i+1] = ckt->CKTdeltaOld[i];
687     ckt->CKTdeltaOld[0] = ckt->CKTdelta;
688 
689     temp = ckt->CKTstates[ckt->CKTmaxOrder+1];
690     for(i=ckt->CKTmaxOrder;i>=0;i--) {
691         ckt->CKTstates[i+1] = ckt->CKTstates[i];
692     }
693     ckt->CKTstates[0] = temp;
694 
695 /* 600 */
696     for (;;) {
697 #if defined CLUSTER || defined SHARED_MODULE
698         redostep = 1;
699 #endif
700 #ifdef XSPICE
701 /* gtri - add - wbk - 4/17/91 - Fix Berkeley bug */
702 /* This is needed here to allow CAPask to output currents */
703 /* during Transient analysis.  A grep for CKTcurrentAnalysis */
704 /* indicates that it should not hurt anything else ... */
705 
706         ckt->CKTcurrentAnalysis = DOING_TRAN;
707 
708 /* gtri - end - wbk - 4/17/91 - Fix Berkeley bug */
709 #endif
710         olddelta=ckt->CKTdelta;
711         /* time abort? */
712         ckt->CKTtime += ckt->CKTdelta;
713 #ifdef CLUSTER
714         CLUinput(ckt);
715 #endif
716         ckt->CKTdeltaOld[0]=ckt->CKTdelta;
717         NIcomCof(ckt);
718 #ifdef PREDICTOR
719         error = NIpred(ckt);
720 #endif /* PREDICTOR */
721         save_mode = ckt->CKTmode;
722         save_order = ckt->CKTorder;
723 #ifdef XSPICE
724 /* gtri - begin - wbk - Add Breakpoint stuff */
725 
726         /* Initialize temporary breakpoint to infinity */
727         g_mif_info.breakpoint.current = 1.0e30;
728 
729 /* gtri - end - wbk - Add Breakpoint stuff */
730 
731 
732 /* gtri - begin - wbk - add convergence problem reporting flags */
733         /* delta is forced to equal delmin on last attempt near line 650 */
734         if(ckt->CKTdelta <= ckt->CKTdelmin)
735             ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
736         else
737             ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
738 /* gtri - begin - wbk - add convergence problem reporting flags */
739 
740 
741 /* gtri - begin - wbk - Call all hybrids */
742 
743 /* gtri - begin - wbk - Set evt_step */
744 
745         if(ckt->evt->counts.num_insts > 0) {
746             g_mif_info.circuit.evt_step = ckt->CKTtime;
747         }
748 /* gtri - end - wbk - Set evt_step */
749 #endif
750 
751         converged = NIiter(ckt,ckt->CKTtranMaxIter);
752 
753 #ifdef XSPICE
754         if(ckt->evt->counts.num_insts > 0) {
755             g_mif_info.circuit.evt_step = ckt->CKTtime;
756             EVTcall_hybrids(ckt);
757         }
758 /* gtri - end - wbk - Call all hybrids */
759 
760 #endif
761         ckt->CKTstat->STATtimePts ++;
762         ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITPRED;
763         if(firsttime) {
764             memcpy(ckt->CKTstate2, ckt->CKTstate1,
765                    (size_t) ckt->CKTnumStates * sizeof(double));
766             memcpy(ckt->CKTstate3, ckt->CKTstate1,
767                    (size_t) ckt->CKTnumStates * sizeof(double));
768         }
769         /* txl, cpl addition */
770         if (converged == 1111) {
771                 return(converged);
772         }
773 
774         if(converged != 0) {
775 #ifndef CLUSTER
776 #ifndef SHARED_MODULE
777             ckt->CKTtime = ckt->CKTtime -ckt->CKTdelta;
778             ckt->CKTstat->STATrejected ++;
779 #else
780             redostep = 1;
781 #endif
782 #endif
783             ckt->CKTdelta = ckt->CKTdelta/8;
784 #ifdef STEPDEBUG
785             (void)printf("delta cut to %g for non-convergence\n",ckt->CKTdelta);
786             fflush(stdout);
787 #endif
788             if(firsttime) {
789                 ckt->CKTmode = (ckt->CKTmode&MODEUIC) | MODETRAN | MODEINITTRAN;
790             }
791             ckt->CKTorder = 1;
792 
793 #ifdef XSPICE
794 /* gtri - begin - wbk - Add Breakpoint stuff */
795 
796         /* Force backup if temporary breakpoint is < current time */
797         } else if(g_mif_info.breakpoint.current < ckt->CKTtime) {
798             ckt->CKTsaveDelta = ckt->CKTdelta;
799             ckt->CKTtime -= ckt->CKTdelta;
800             ckt->CKTdelta = g_mif_info.breakpoint.current - ckt->CKTtime;
801             g_mif_info.breakpoint.last = ckt->CKTtime + ckt->CKTdelta;
802 
803             if(firsttime) {
804                 ckt->CKTmode = (ckt->CKTmode&MODEUIC)|MODETRAN | MODEINITTRAN;
805             }
806             ckt->CKTorder = 1;
807 
808 /* gtri - end - wbk - Add Breakpoint stuff */
809 #endif
810 
811         } else {
812             if (firsttime) {
813 #ifdef WANT_SENSE2
814                 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){
815                     save1 = ckt->CKTmode;
816                     save2 = ckt->CKTorder;
817                     ckt->CKTmode = save_mode;
818                     ckt->CKTorder = save_order;
819                     error = CKTsenDCtran (ckt);
820                     if (error)
821                         return(error);
822 
823                     ckt->CKTmode = save1;
824                     ckt->CKTorder = save2;
825                 }
826 #endif
827                 firsttime = 0;
828 #if !defined CLUSTER && !defined SHARED_MODULE
829                 goto nextTime;  /* no check on
830                                  * first time point
831                                  */
832 #else
833                 redostep = 0;
834                 goto chkStep;
835 #endif
836             }
837             newdelta = ckt->CKTdelta;
838             error = CKTtrunc(ckt,&newdelta);
839             if(error) {
840                 UPDATE_STATS(DOING_TRAN);
841                 return(error);
842             }
843             if (newdelta > .9 * ckt->CKTdelta) {
844                 if ((ckt->CKTorder == 1) && (ckt->CKTmaxOrder > 1)) { /* don't rise the order for backward Euler */
845                     newdelta = ckt->CKTdelta;
846                     ckt->CKTorder = 2;
847                     error = CKTtrunc(ckt, &newdelta);
848                     if (error) {
849                         UPDATE_STATS(DOING_TRAN);
850                         return(error);
851                     }
852                     if (newdelta <= 1.05 * ckt->CKTdelta) {
853                         ckt->CKTorder = 1;
854                     }
855                 }
856                 /* time point OK  - 630 */
857                 ckt->CKTdelta = newdelta;
858 #ifdef NDEV
859                 if (!ft_norefprint) {
860                     /* show a time process indicator, by Gong Ding, gdiso@ustc.edu */
861                     if (ckt->CKTtime / ckt->CKTfinalTime * 100 < 10.0)
862                         printf("%%%3.2lf\b\b\b\b\b", ckt->CKTtime / ckt->CKTfinalTime * 100);
863                     else  if (ckt->CKTtime / ckt->CKTfinalTime * 100 < 100.0)
864                         printf("%%%4.2lf\b\b\b\b\b\b", ckt->CKTtime / ckt->CKTfinalTime * 100);
865                     else
866                         printf("%%%5.2lf\b\b\b\b\b\b\b", ckt->CKTtime / ckt->CKTfinalTime * 100);
867                     fflush(stdout);
868                 }
869 #endif
870 
871 #ifdef STEPDEBUG
872                 (void)printf(
873                   "delta set to truncation error result: %g. Point accepted at CKTtime: %g\n",
874                   ckt->CKTdelta,ckt->CKTtime);
875                 fflush(stdout);
876 #endif
877 
878 #ifdef WANT_SENSE2
879                 if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN)){
880                     save1 = ckt->CKTmode;
881                     save2 = ckt->CKTorder;
882                     ckt->CKTmode = save_mode;
883                     ckt->CKTorder = save_order;
884                     error = CKTsenDCtran(ckt);
885                     if (error)
886                         return (error);
887 
888                     ckt->CKTmode = save1;
889                     ckt->CKTorder = save2;
890                 }
891 #endif
892 
893 #if !defined CLUSTER && !defined SHARED_MODULE
894                 /* go to 650 - trapezoidal */
895                 goto nextTime;
896 #else
897                 redostep = 0;
898                 goto chkStep;
899 #endif
900             } else {
901 #ifndef CLUSTER
902 #ifndef SHARED_MODULE
903                 ckt->CKTtime = ckt->CKTtime -ckt->CKTdelta;
904                 ckt->CKTstat->STATrejected ++;
905 #else
906                 redostep = 1;
907 #endif
908 #endif
909                 ckt->CKTdelta = newdelta;
910 #ifdef STEPDEBUG
911                 (void)printf(
912                     "delta set to truncation error result:point rejected\n");
913 #endif
914             }
915         }
916 
917         if (ckt->CKTdelta <= ckt->CKTdelmin) {
918             if (olddelta > ckt->CKTdelmin) {
919                 ckt->CKTdelta = ckt->CKTdelmin;
920 #ifdef STEPDEBUG
921                 (void)printf("delta at delmin\n");
922 #endif
923             } else {
924                 UPDATE_STATS(DOING_TRAN);
925                 errMsg = CKTtrouble(ckt, "Timestep too small");
926                 return(E_TIMESTEP);
927             }
928         }
929 #ifdef XSPICE
930 /* gtri - begin - wbk - Do event backup */
931 
932         if(ckt->evt->counts.num_insts > 0)
933             EVTbackup(ckt, ckt->CKTtime + ckt->CKTdelta);
934 
935 /* gtri - end - wbk - Do event backup */
936 #endif
937 #ifdef CLUSTER
938         chkStep:
939         if(CLUsync(ckt->CKTtime,&ckt->CKTdelta,redostep)){
940             goto nextTime;
941         } else {
942             ckt->CKTtime -= olddelta;
943             ckt->CKTstat->STATrejected ++;
944         }
945 #endif
946 
947 #ifdef SHARED_MODULE
948         /* redostep == 0:
949            Either directly go to next time step, or modify ckt->CKTdelta depending on
950            synchronization requirements. sharedsync() returns 0.
951            redostep == 1:
952            No convergence, or too large truncation error.
953            Redo the last time step by subtracting olddelta, and modify ckt->CKTdelta
954            depending on synchronization requirements. sharedsync() returns 1.
955            User-supplied redo request:
956            sharedsync() may return 1 if the user has decided to do so in the callback
957            function.
958         */
959 chkStep:
960         if(sharedsync(&ckt->CKTtime, &ckt->CKTdelta, olddelta, ckt->CKTfinalTime,
961                  ckt->CKTdelmin, redostep, &ckt->CKTstat->STATrejected, 1) == 0)
962             goto nextTime;
963 #endif
964 
965     }
966     /* NOTREACHED */
967 }
968