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