1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 Author: 1985 Thomas L. Quarles
4 Modified: 2000  AlansFixes
5 Modified: 2005 Paolo Nenzi - Restructured
6 **********/
7 
8 #include "ngspice/ngspice.h"
9 #include "ngspice/cktdefs.h"
10 #include "ngspice/devdefs.h"
11 #include "ngspice/sperror.h"
12 #include "ngspice/cpextern.h"
13 
14 #ifdef XSPICE
15 #include "ngspice/enh.h"
16 #endif
17 
18 
19 static int dynamic_gmin(CKTcircuit *, long int, long int, int);
20 static int spice3_gmin(CKTcircuit *, long int, long int, int);
21 static int new_gmin(CKTcircuit*, long int, long int, int);
22 static int gillespie_src(CKTcircuit *, long int, long int, int);
23 static int spice3_src(CKTcircuit *, long int, long int, int);
24 
25 
26 int
CKTop(CKTcircuit * ckt,long int firstmode,long int continuemode,int iterlim)27 CKTop (CKTcircuit *ckt, long int firstmode, long int continuemode,
28        int iterlim)
29 {
30     int converged;
31 
32 #ifdef HAS_PROGREP
33     SetAnalyse("op", 0);
34 #endif
35 
36     ckt->CKTmode = firstmode;
37 
38     if (!ckt->CKTnoOpIter) {
39 #ifdef XSPICE
40         /* gtri - wbk - add convergence problem reporting flags */
41         ckt->enh->conv_debug.last_NIiter_call =
42             (ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0);
43 #endif
44         converged = NIiter (ckt, iterlim);
45         if (converged == 0)
46             return converged;   /* successfull */
47     } else {
48         converged = 1;          /* the 'go directly to gmin stepping' option */
49     }
50 
51 
52     /* no convergence on the first try, so we do something else */
53     /* first, check if we should try gmin stepping */
54 
55     if (ckt->CKTnumGminSteps >= 1) {
56         if (ckt->CKTnumGminSteps == 1) {
57             /* only the old gmin */
58             if (cp_getvar("dyngmin", CP_BOOL, NULL, 0)) {
59                 converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim);
60             }
61             /* first the new gmin, then the old gmin */
62             else {
63                 converged = new_gmin(ckt, firstmode, continuemode, iterlim);
64                 if(converged != 0) {
65                     converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim);
66                 }
67 
68             }
69         }
70         else {
71             converged = spice3_gmin(ckt, firstmode, continuemode, iterlim);
72         }
73         if (converged == 0) /* If gmin-stepping worked... move out */
74             return converged;
75     }
76 
77     /* ... otherwise try stepping sources ...
78      * now, we'll try source stepping - we scale the sources
79      * to 0, converge, then start stepping them up until they
80      * are at their normal values
81      */
82 
83     if (ckt->CKTnumSrcSteps >= 1) {
84         if (ckt->CKTnumSrcSteps == 1)
85             converged = gillespie_src(ckt, firstmode, continuemode, iterlim);
86         else
87             converged = spice3_src(ckt, firstmode, continuemode, iterlim);
88     }
89 
90 #ifdef XSPICE
91     /* gtri - wbk - add convergence problem reporting flags */
92     ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
93 #endif
94 
95     return converged;
96 }
97 
98 
99 /* CKTconvTest(ckt)
100  *    this is a driver program to iterate through all the various
101  *    convTest functions provided for the circuit elements in the
102  *    given circuit
103  */
104 
105 int
CKTconvTest(CKTcircuit * ckt)106 CKTconvTest (CKTcircuit *ckt)
107 {
108     int i;
109 
110     for (i = 0; i < DEVmaxnum; i++) {
111 
112         if (DEVices[i] && DEVices[i]->DEVconvTest && ckt->CKThead[i]) {
113             int error = DEVices[i]->DEVconvTest (ckt->CKThead[i], ckt);
114             if (error)
115                 return error;
116         }
117 
118         if (ckt->CKTnoncon) {
119             /* printf("convTest: device %s failed\n",
120              * DEVices[i]->DEVpublic.name); */
121             return OK;
122         }
123     }
124 
125     return OK;
126 }
127 
128 
129 /* Dynamic gmin stepping
130  * Algorithm by Alan Gillespie
131  * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
132  *
133  * return value:
134  * 0 -> method converged
135  * 1 -> method failed
136  *
137  * Note that no path out of this code allows ckt->CKTdiagGmin to be
138  * anything but CKTgshunt.
139  */
140 
141 static int
dynamic_gmin(CKTcircuit * ckt,long int firstmode,long int continuemode,int iterlim)142 dynamic_gmin (CKTcircuit *ckt, long int firstmode,
143               long int continuemode, int iterlim)
144 {
145     double OldGmin, gtarget, factor;
146     int converged;
147 
148     int NumNodes, iters, i;
149     double *OldRhsOld, *OldCKTstate0;
150     CKTnode *n;
151 
152     ckt->CKTmode = firstmode;
153     SPfrontEnd->IFerrorf (ERR_INFO, "Starting dynamic gmin stepping");
154 
155     NumNodes = 0;
156     for (n = ckt->CKTnodes; n; n = n->next)
157         NumNodes++;
158 
159     OldRhsOld = TMALLOC(double, NumNodes + 1);
160     OldCKTstate0 = TMALLOC(double, ckt->CKTnumStates + 1);
161 
162     for (n = ckt->CKTnodes; n; n = n->next)
163         ckt->CKTrhsOld [n->number] = 0;
164 
165     for (i = 0; i < ckt->CKTnumStates; i++)
166         ckt->CKTstate0 [i] = 0;
167 
168     factor = ckt->CKTgminFactor;
169     OldGmin = 1e-2;
170     ckt->CKTdiagGmin = OldGmin / factor;
171     gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt);
172 
173     for (;;) {
174         fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
175 
176         ckt->CKTnoncon = 1;
177         iters = ckt->CKTstat->STATnumIter;
178         converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
179         iters = ckt->CKTstat->STATnumIter - iters;
180 
181         if (converged == 0) {
182             ckt->CKTmode = continuemode;
183             SPfrontEnd->IFerrorf (ERR_INFO, "One successful gmin step");
184 
185             if (ckt->CKTdiagGmin <= gtarget)
186                 break;          /* successfull */
187 
188             for (i = 0, n = ckt->CKTnodes; n; n = n->next)
189                 OldRhsOld[i++] = ckt->CKTrhsOld[n->number];
190 
191             memcpy(OldCKTstate0, ckt->CKTstate0,
192                    (size_t) ckt->CKTnumStates * sizeof(double));
193 
194             if (iters <= (ckt->CKTdcTrcvMaxIter / 4)) {
195                 factor *= sqrt (factor);
196                 if (factor > ckt->CKTgminFactor)
197                     factor = ckt->CKTgminFactor;
198             }
199 
200             if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))
201                 factor = MAX(sqrt (factor), 1.00005);
202 
203             OldGmin = ckt->CKTdiagGmin;
204 
205             if (ckt->CKTdiagGmin < factor * gtarget) {
206                 factor = ckt->CKTdiagGmin / gtarget;
207                 ckt->CKTdiagGmin = gtarget;
208             } else {
209                 ckt->CKTdiagGmin /= factor;
210             }
211         } else {
212             if (factor < 1.00005) {
213                 SPfrontEnd->IFerrorf (ERR_WARNING, "Last gmin step failed");
214                 break;          /* failed */
215             }
216             SPfrontEnd->IFerrorf (ERR_WARNING, "Further gmin increment");
217             factor = sqrt (sqrt (factor));
218             ckt->CKTdiagGmin = OldGmin / factor;
219 
220             for (i = 0, n = ckt->CKTnodes; n; n = n->next)
221                 ckt->CKTrhsOld[n->number] = OldRhsOld[i++];
222 
223             memcpy(ckt->CKTstate0, OldCKTstate0,
224                    (size_t) ckt->CKTnumStates * sizeof(double));
225         }
226     }
227 
228     ckt->CKTdiagGmin = ckt->CKTgshunt;
229     FREE (OldRhsOld);
230     FREE (OldCKTstate0);
231 
232 #ifdef XSPICE
233     /* gtri - wbk - add convergence problem reporting flags */
234     ckt->enh->conv_debug.last_NIiter_call = (ckt->CKTnumSrcSteps <= 0);
235 #endif
236 
237     converged = NIiter (ckt, iterlim);
238 
239     if (converged != 0) {
240         SPfrontEnd->IFerrorf (ERR_WARNING, "Dynamic gmin stepping failed");
241     } else {
242         SPfrontEnd->IFerrorf (ERR_INFO, "Dynamic gmin stepping completed");
243 #ifdef XSPICE
244         /* gtri - wbk - add convergence problem reporting flags */
245         ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
246 #endif
247     }
248 
249     return converged;
250 }
251 
252 
253 /* Spice3 gmin stepping
254  * Modified 2000 - Alan Gillespie (added gshunt)
255  * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
256  *
257  * return value:
258  * 0 -> method converged
259  * 1 -> method failed
260  *
261  * Note that no path out of this code allows ckt->CKTdiagGmin to be
262  * anything but CKTgshunt.
263  */
264 
265 static int
spice3_gmin(CKTcircuit * ckt,long int firstmode,long int continuemode,int iterlim)266 spice3_gmin (CKTcircuit *ckt, long int firstmode,
267              long int continuemode, int iterlim)
268 {
269     int converged, i;
270 
271     ckt->CKTmode = firstmode;
272     SPfrontEnd->IFerrorf (ERR_INFO, "Starting gmin stepping");
273 
274     ckt->CKTdiagGmin =
275         (ckt->CKTgshunt == 0) ? ckt->CKTgmin :  ckt->CKTgshunt;
276 
277     for (i = 0; i < ckt->CKTnumGminSteps; i++)
278         ckt->CKTdiagGmin *= ckt->CKTgminFactor;
279 
280     for (i = 0; i <= ckt->CKTnumGminSteps; i++) {
281         fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
282 
283         ckt->CKTnoncon = 1;
284         converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
285 
286         if (converged != 0) {
287             ckt->CKTdiagGmin = ckt->CKTgshunt;
288             SPfrontEnd->IFerrorf (ERR_WARNING, "gmin step failed");
289             break;
290         }
291 
292         ckt->CKTdiagGmin /= ckt->CKTgminFactor;
293         ckt->CKTmode = continuemode;
294 
295         SPfrontEnd->IFerrorf (ERR_INFO, "One successful gmin step");
296     }
297 
298     ckt->CKTdiagGmin = ckt->CKTgshunt;
299 
300 #ifdef XSPICE
301     /* gtri - wbk - add convergence problem reporting flags */
302     ckt->enh->conv_debug.last_NIiter_call = (ckt->CKTnumSrcSteps <= 0);
303 #endif
304 
305     converged = NIiter (ckt, iterlim);
306 
307     if (converged == 0) {
308         SPfrontEnd->IFerrorf (ERR_INFO, "gmin stepping completed");
309 
310 #ifdef XSPICE
311         /* gtri - wbk - add convergence problem reporting flags */
312         ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
313 #endif
314 
315     } else {
316         SPfrontEnd->IFerrorf (ERR_WARNING, "gmin stepping failed");
317     }
318 
319     return converged;
320 }
321 
322 /* just step the real gmin found in every device model */
323 static int
new_gmin(CKTcircuit * ckt,long int firstmode,long int continuemode,int iterlim)324 new_gmin(CKTcircuit* ckt, long int firstmode,
325     long int continuemode, int iterlim)
326 {
327     double OldGmin, gtarget, factor, startgmin;
328     int converged;
329 
330     int NumNodes, iters, i;
331     double* OldRhsOld, * OldCKTstate0;
332     CKTnode* n;
333 
334     ckt->CKTmode = firstmode;
335     SPfrontEnd->IFerrorf(ERR_INFO, "Starting true gmin stepping");
336 
337     NumNodes = 0;
338     for (n = ckt->CKTnodes; n; n = n->next)
339         NumNodes++;
340 
341     OldRhsOld = TMALLOC(double, NumNodes + 1);
342     OldCKTstate0 = TMALLOC(double, ckt->CKTnumStates + 1);
343 
344     for (n = ckt->CKTnodes; n; n = n->next)
345         ckt->CKTrhsOld[n->number] = 0;
346 
347     for (i = 0; i < ckt->CKTnumStates; i++)
348         ckt->CKTstate0[i] = 0;
349 
350     startgmin = ckt->CKTgmin;
351     factor = ckt->CKTgminFactor;
352     OldGmin = 1e-2;
353     /*ckt->CKTdiagGmin = */ckt->CKTgmin = OldGmin / factor;
354     gtarget = MAX(startgmin, ckt->CKTgshunt);
355 
356     for (;;) {
357         fprintf(stderr, "Trying gmin = %12.4E ", ckt->CKTgmin);
358 
359         ckt->CKTnoncon = 1;
360         iters = ckt->CKTstat->STATnumIter;
361         converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter);
362         iters = ckt->CKTstat->STATnumIter - iters;
363 
364         if (converged == 0) {
365             ckt->CKTmode = continuemode;
366             SPfrontEnd->IFerrorf(ERR_INFO, "One successful gmin step");
367 
368             if (ckt->CKTgmin <= gtarget)
369                 break;          /* successfull */
370 
371             for (i = 0, n = ckt->CKTnodes; n; n = n->next)
372                 OldRhsOld[i++] = ckt->CKTrhsOld[n->number];
373 
374             memcpy(OldCKTstate0, ckt->CKTstate0,
375                 (size_t)ckt->CKTnumStates * sizeof(double));
376 
377             if (iters <= (ckt->CKTdcTrcvMaxIter / 4)) {
378                 factor *= sqrt(factor);
379                 if (factor > ckt->CKTgminFactor)
380                     factor = ckt->CKTgminFactor;
381             }
382 
383             if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))
384                 factor = MAX(sqrt(factor), 1.00005);
385 
386             OldGmin = ckt->CKTgmin;
387 
388             if (ckt->CKTgmin < factor * gtarget) {
389                 factor = ckt->CKTgmin / gtarget;
390                 /*ckt->CKTdiagGmin = */ckt->CKTgmin = gtarget;
391             }
392             else {
393                 /*ckt->CKTdiagGmin = */ckt->CKTgmin /= factor;
394             }
395         }
396         else {
397             if (factor < 1.00005) {
398                 SPfrontEnd->IFerrorf(ERR_WARNING, "Last gmin step failed");
399                 break;          /* failed */
400             }
401             SPfrontEnd->IFerrorf(ERR_WARNING, "Further gmin increment");
402             factor = sqrt(sqrt(factor));
403             /*ckt->CKTdiagGmin = */ckt->CKTgmin = OldGmin / factor;
404 
405             for (i = 0, n = ckt->CKTnodes; n; n = n->next)
406                 ckt->CKTrhsOld[n->number] = OldRhsOld[i++];
407 
408             memcpy(ckt->CKTstate0, OldCKTstate0,
409                 (size_t)ckt->CKTnumStates * sizeof(double));
410         }
411     }
412 
413     /*ckt->CKTdiagGmin = */ckt->CKTgmin = MAX(startgmin, ckt->CKTgshunt);
414     FREE(OldRhsOld);
415     FREE(OldCKTstate0);
416 
417 #ifdef XSPICE
418     /* gtri - wbk - add convergence problem reporting flags */
419     ckt->enh->conv_debug.last_NIiter_call = (ckt->CKTnumSrcSteps <= 0);
420 #endif
421 
422     converged = NIiter(ckt, iterlim);
423 
424     if (converged != 0) {
425         SPfrontEnd->IFerrorf(ERR_WARNING, "True gmin stepping failed");
426     }
427     else {
428         SPfrontEnd->IFerrorf(ERR_INFO, "True gmin stepping completed");
429 #ifdef XSPICE
430         /* gtri - wbk - add convergence problem reporting flags */
431         ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
432 #endif
433     }
434 
435     return converged;
436 }
437 
438 
439 /* Gillespie's Source stepping
440  * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
441  *
442  * return value:
443  * 0 -> method converged
444  * 1 -> method failed
445  *
446  * Note that no path out of this code allows ckt->CKTsrcFact to be
447  * anything but 1.00000.
448  */
449 
450 static int
gillespie_src(CKTcircuit * ckt,long int firstmode,long int continuemode,int iterlim)451 gillespie_src (CKTcircuit *ckt, long int firstmode,
452                long int continuemode, int iterlim)
453 {
454     int converged, i, iters;
455     double ConvFact;
456     CKTnode *n;
457     double gminstart = ckt->CKTgmin;
458 
459     NG_IGNORE(iterlim);
460 
461     ckt->CKTmode = firstmode;
462     SPfrontEnd->IFerrorf (ERR_INFO, "Starting source stepping");
463 
464     ckt->CKTsrcFact = 0;
465     ConvFact = 0;
466 
467     for (n = ckt->CKTnodes; n; n = n->next)
468         ckt->CKTrhsOld[n->number] = 0;
469 
470     for (i = 0; i < ckt->CKTnumStates; i++)
471         ckt->CKTstate0[i] = 0;
472 
473     /*  First, try a straight solution with all sources at zero */
474 
475     fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100);
476     converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
477 
478     /*  If this doesn't work, try gmin stepping as well for the first solution */
479 
480     if (converged != 0) {
481         fprintf (stderr, "\n");
482 
483         ckt->CKTdiagGmin =
484             (ckt->CKTgshunt <= 0) ? ckt->CKTgmin : ckt->CKTgshunt;
485 
486         for (i = 0; i < 10; i++)
487             ckt->CKTdiagGmin *= 10;
488 
489         for (i = 0; i <= 10; i++) {
490             fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
491 
492 #ifdef XSPICE
493             /* gtri - wbk - add convergence problem reporting flags */
494             ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
495 #endif
496 
497             ckt->CKTnoncon = 1;
498             converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
499 
500             if (converged != 0) {
501                 ckt->CKTdiagGmin = ckt->CKTgshunt;
502                 SPfrontEnd->IFerrorf (ERR_WARNING, "gmin step failed");
503 #ifdef XSPICE
504                 /* gtri - wbk - add convergence problem reporting flags */
505                 ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
506 #endif
507                 break;
508             }
509 
510             ckt->CKTdiagGmin /= 10;
511             ckt->CKTmode = continuemode;
512             SPfrontEnd->IFerrorf (ERR_INFO, "One successful gmin step");
513         }
514         ckt->CKTdiagGmin = ckt->CKTgshunt;
515     }
516 
517     /*  If we've got convergence, then try stepping up the sources  */
518 
519     if (converged == 0) {
520 
521         double *OldRhsOld, *OldCKTstate0, raise = 0.001;
522 
523         int NumNodes = 0;
524         for (n = ckt->CKTnodes; n; n = n->next)
525             NumNodes++;
526 
527         OldRhsOld = TMALLOC(double, NumNodes + 1);
528         OldCKTstate0 = TMALLOC(double, ckt->CKTnumStates + 1);
529 
530         for (i = 0, n = ckt->CKTnodes; n; n = n->next)
531             OldRhsOld[i++] = ckt->CKTrhsOld[n->number];
532 
533         memcpy(OldCKTstate0, ckt->CKTstate0,
534                (size_t) ckt->CKTnumStates * sizeof(double));
535 
536         SPfrontEnd->IFerrorf (ERR_INFO, "One successful source step");
537         ckt->CKTsrcFact = ConvFact + raise;
538 
539         do {
540             fprintf (stderr,
541                      "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100);
542 
543 #ifdef XSPICE
544             /* gtri - wbk - add convergence problem reporting flags */
545             ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
546 #endif
547 
548             iters = ckt->CKTstat->STATnumIter;
549             converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
550             iters = ckt->CKTstat->STATnumIter - iters;
551 
552             ckt->CKTmode = continuemode;
553 
554             if (converged == 0) {
555                 ConvFact = ckt->CKTsrcFact;
556 
557                 for (i = 0, n = ckt->CKTnodes; n; n = n->next)
558                     OldRhsOld[i++] = ckt->CKTrhsOld[n->number];
559 
560                 memcpy(OldCKTstate0, ckt->CKTstate0,
561                        (size_t) ckt->CKTnumStates * sizeof(double));
562 
563                 SPfrontEnd->IFerrorf (ERR_INFO, "One successful source step");
564 
565                 ckt->CKTsrcFact = ConvFact + raise;
566 
567                 if (iters <= (ckt->CKTdcTrcvMaxIter / 4))
568                     raise *= 1.5;
569 
570                 if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))
571                     raise *= 0.5;
572 
573                 /* if (raise > 0.01)
574                  *     raise = 0.01;
575                  */
576 
577             }
578 /*            else if (ckt->CKTgmin < 1e-3){
579                 ckt->CKTdiagGmin = ckt->CKTgmin *= 10;
580                 fprintf(stderr,
581                     "gmin raised to %8.4e\n", ckt->CKTgmin);
582             }*/
583             else {
584 
585                 if (ckt->CKTsrcFact - ConvFact < 1e-8)
586                     break;
587 
588                 raise /= 10;
589 
590                 if (raise > 0.01)
591                     raise = 0.01;
592 
593                 ckt->CKTsrcFact = ConvFact;
594 
595                 for (i = 0, n = ckt->CKTnodes; n; n = n->next)
596                     ckt->CKTrhsOld[n->number] = OldRhsOld[i++];
597 
598                 memcpy(ckt->CKTstate0, OldCKTstate0,
599                        (size_t) ckt->CKTnumStates * sizeof(double));
600             }
601 
602             if (ckt->CKTsrcFact > 1)
603                 ckt->CKTsrcFact = 1;
604 
605         } while ((raise >= 1e-7) && (ConvFact < 1));
606 
607         ckt->CKTdiagGmin = ckt->CKTgmin = gminstart;
608         FREE (OldRhsOld);
609         FREE (OldCKTstate0);
610     }
611 
612     ckt->CKTsrcFact = 1;
613 
614     if (ConvFact != 1) {
615         ckt->CKTcurrentAnalysis = DOING_TRAN;
616         SPfrontEnd->IFerrorf (ERR_WARNING, "source stepping failed");
617         return E_ITERLIM;
618     } else {
619         SPfrontEnd->IFerrorf (ERR_INFO, "Source stepping completed");
620         return 0;
621     }
622 }
623 
624 
625 /* Spice3 Source stepping
626  * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code)
627  *
628  * return value:
629  * 0 -> method converged
630  * 1 -> method failed
631  *
632  * Note that no path out of this code allows ckt->CKTsrcFact to be
633  * anything but 1.00000.
634  */
635 
636 static int
spice3_src(CKTcircuit * ckt,long int firstmode,long int continuemode,int iterlim)637 spice3_src (CKTcircuit *ckt, long int firstmode,
638             long int continuemode, int iterlim)
639 {
640     int converged, i;
641 
642     NG_IGNORE(iterlim);
643 
644     ckt->CKTmode = firstmode;
645     SPfrontEnd->IFerrorf (ERR_INFO, "Starting source stepping");
646 
647     for (i = 0; i <= ckt->CKTnumSrcSteps; i++) {
648         ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps);
649 #ifdef XSPICE
650         /* gtri - wbk - add convergence problem reporting flags */
651         ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
652 #endif
653         converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
654         ckt->CKTmode = continuemode;
655         if (converged != 0) {
656             ckt->CKTsrcFact = 1;
657             ckt->CKTcurrentAnalysis = DOING_TRAN;
658             SPfrontEnd->IFerrorf (ERR_WARNING, "source stepping failed");
659 #ifdef XSPICE
660             /* gtri - wbk - add convergence problem reporting flags */
661             ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
662 #endif
663             return converged;
664         }
665         SPfrontEnd->IFerrorf (ERR_INFO, "One successful source step");
666     }
667 
668     SPfrontEnd->IFerrorf (ERR_INFO, "Source stepping completed");
669     ckt->CKTsrcFact = 1;
670 
671 #ifdef XSPICE
672     /* gtri - wbk - add convergence problem reporting flags */
673     ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;
674 #endif
675 
676     return 0;
677 }
678