Jspice3
niiter.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Thomas L. Quarles
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 /*
9  * NIiter(ckt,maxIter)
10  *
11  * This subroutine performs the actual numerical iteration.
12  * It uses the sparse matrix stored in the circuit struct
13  * along with the matrix loading program, the load data, the
14  * convergence test function, and the convergence parameters
15  */
16 
17 #include "spice.h"
18 #include <stdio.h>
19 #include "cktdefs.h"
20 #include "optdefs.h"
21 #include "sperror.h"
22 #include "util.h"
23 #include "cktext.h"
24 #include "niext.h"
25 
26 /* NIiter() - return value is non-zero for convergence failure */
27 
28 int
29 NIiter(ckt,maxIter)
30 
31 CKTcircuit * ckt;
32 int maxIter;
33 {
34  int iterno;
35  int ipass;
36  int error;
37  int i,j; /* temporaries for finding error location */
38  char *message; /* temporary message buffer */
39  double *temp;
40  double startTime;
41  static char *msg = "Too many iterations without convergence";
42  STATistics *stat = (STATistics*)ckt->CKTstat;
43 
44  /* assume that NIreinit() has been called */
45  iterno = 0;
46  ipass = 0;
47  ckt->CKTnoncon = 0;
48 
49  error = CKTload(ckt);
50  if (error) {
51 #ifdef STEPDEBUG
52  printf("load (1) returned error\n");
53 #endif
54  return (error);
55  }
56 
57  if (!(ckt->CKTniState & NIDIDPREORDER)) {
58  spMNA_Preorder(ckt->CKTmatrix);
59  error = spError(ckt->CKTmatrix);
60  if (error) {
61  /* badly formed matrix */
62 #ifdef STEPDEBUG
63  printf("pre-order returned error \n");
64 #endif
65  return (error);
66  }
67  ckt->CKTniState |= NIDIDPREORDER;
68  }
69 
70  if ((ckt->CKTmode & MODEINITJCT) ||
71  (ckt->CKTmode & MODEINITTRAN)) {
72  ckt->CKTniState |= NISHOULDREORDER;
73  }
74 
75  for (;;) {
76 
77  if (ckt->CKTmode & MODEINITFLOAT) {
78  if (ckt->CKTnoncon == 0 && ckt->CKTjjPresent) {
79  error = OK;
80  break;
81  }
82  }
83  iterno++;
84 
85  if (ckt->CKTniState & NISHOULDREORDER) {
86  startTime = (*(SPfrontEnd->IFseconds))();
87  spSetReal(ckt->CKTmatrix);
88  spLoadGmin(ckt->CKTmatrix,ckt->CKTdiagGmin);
89  error = spOrderAndFactor(ckt->CKTmatrix,NULL,
90  ckt->CKTpivotRelTol,ckt->CKTpivotAbsTol,1);
91  stat->STATreorderTime +=
92  (*(SPfrontEnd->IFseconds))() - startTime;
93  if (error) {
94  /* new feature - we can now find out something about what is
95  * wrong - so we ask for the troublesome entry
96  */
97  spWhereSingular(ckt->CKTmatrix,&i,&j);
98  message = (char *)MALLOC(1000); /* should be enough */
99  (void)sprintf(message,
100  "singular matrix: check nodes %s and %s\n",
101  NODENAME(ckt,i),NODENAME(ckt,j));
102  (*(SPfrontEnd->IFerror))(ERR_WARNING,message,(IFuid *)NULL);
103  FREE(message);
104  /* can't handle these errors - pass up! */
105 #ifdef STEPDEBUG
106  printf("reorder returned error ");
107  if (ckt->CKTmode & MODETRAN)
108  printf("at time=%g",ckt->CKTtime);
109  printf("\n");
110 #endif
111  break;
112  }
113  ckt->CKTniState &= ~NISHOULDREORDER;
114  spGetStat(ckt->CKTmatrix,
115  &stat->STATmatSize,
116  &stat->STATnonZero,
117  &stat->STATfillIn);
118  }
119  else {
120  startTime = (*(SPfrontEnd->IFseconds))();
121  spSetReal(ckt->CKTmatrix);
122  spLoadGmin(ckt->CKTmatrix,ckt->CKTdiagGmin);
123  error = spFactor(ckt->CKTmatrix);
124  stat->STATdecompTime +=
125  (*(SPfrontEnd->IFseconds))() - startTime;
126  if (error) {
127  if (error == E_SINGULAR) {
128  ckt->CKTniState |= NISHOULDREORDER;
129  DEBUGMSG(" forced reordering....\n");
130  error = CKTload(ckt);
131  if (error) {
132 #ifdef STEPDEBUG
133  printf("load (3) returned error \n");
134 #endif
135  break;
136  }
137  spMNA_Preorder(ckt->CKTmatrix);
138  error = spError(ckt->CKTmatrix);
139  if (error) {
140 #ifdef STEPDEBUG
141  printf("preorder returned error\n");
142 #endif
143  break;
144  }
145  ckt->CKTniState |= NIDIDPREORDER;
146  continue;
147  }
148  /* seems to be singular - pass the bad news up */
149 #ifdef STEPDEBUG
150  printf("lufac returned error \n");
151 #endif
152  break;
153  }
154  }
155 
156  startTime = (*(SPfrontEnd->IFseconds))();
157  spSolve(ckt->CKTmatrix,ckt->CKTrhs,ckt->CKTrhs,NULL,NULL);
158  stat->STATsolveTime += (*(SPfrontEnd->IFseconds))() - startTime;
159 
160  temp = ckt->CKTrhsOld;
161  ckt->CKTrhsOld = ckt->CKTrhs;
162  ckt->CKTrhs = temp;
163 
164  *ckt->CKTrhs = 0;
165  *ckt->CKTrhsSpare = 0;
166  *ckt->CKTrhsOld = 0;
167 
168  if (iterno > maxIter) {
169  error = E_ITERLIM;
170  errMsg = MALLOC(strlen(msg)+1);
171  strcpy(errMsg,msg);
172 #ifdef STEPDEBUG
173  printf("iterlim exceeded, time = %g\n",ckt->CKTtime);
174 #endif
175  break;
176  }
177  if (!ckt->CKTjjPresent) {
178  if (ckt->CKTnoncon == 0 && iterno != 1) {
179  ckt->CKTnoncon = NIconvTest(ckt);
180  }
181  else {
182  ckt->CKTnoncon = 1;
183  }
184  }
185 
186  if (ckt->CKTmode & MODEINITFLOAT) {
187  if ((ckt->CKTmode & MODEDC) && ckt->CKThadNodeset) {
188  if (ipass) {
189  ckt->CKTnoncon = ipass;
190  }
191  ipass = 0;
192  }
193  if (ckt->CKTnoncon == 0) {
194  error = OK;
195  break;
196  }
197  }
198  else if (ckt->CKTmode & MODEINITPRED) {
199  ckt->CKTmode = (ckt->CKTmode&(~INITF))|MODEINITFLOAT;
200  }
201  else if (ckt->CKTmode & MODEINITTRAN) {
202  if (iterno <= 1) ckt->CKTniState |= NISHOULDREORDER;
203  ckt->CKTmode = (ckt->CKTmode&(~INITF))|MODEINITFLOAT;
204  }
205  else if (ckt->CKTmode & MODEINITSMSIG) {
206  ckt->CKTmode = (ckt->CKTmode&(~INITF))|MODEINITFLOAT;
207  }
208  else if(ckt->CKTmode & MODEINITJCT) {
209  ckt->CKTmode = (ckt->CKTmode&(~INITF))|MODEINITFIX;
210  ckt->CKTniState |= NISHOULDREORDER;
211  }
212  else if (ckt->CKTmode & MODEINITFIX) {
213  if (ckt->CKTnoncon == 0)
214  ckt->CKTmode = (ckt->CKTmode&(~INITF))|MODEINITFLOAT;
215  ipass = 1;
216  }
217  else {
218  error = E_INTERN;
219 #ifdef STEPDEBUG
220  printf("bad initf state \n");
221 #endif
222  break;
223  }
224 
225  ckt->CKTnoncon = 0;
226  error = CKTload(ckt);
227 
228  if (error) {
229 #ifdef STEPDEBUG
230  printf("load (2) returned error \n");
231 #endif
232  break;
233  }
234  }
235  stat->STATnumIter += iterno;
236 #ifdef STEPDEBUG
237  printf("time=%15g, %d iters, %s\n", ckt->CKTtime,iterno,
238  (error==OK) ? "ok" : "fail");
239 #endif
240  return (error);
241 }
#define E_INTERN
Definition: sperror.h:15
int spError()
#define MODEINITPRED
Definition: cktdefs.h:161
#define MODEDC
Definition: cktdefs.h:149
#define MODETRAN
Definition: cktdefs.h:145
char * strcpy()
int STATmatSize
Definition: optdefs.h:23
#define MODEINITFLOAT
Definition: cktdefs.h:156
int STATnonZero
Definition: optdefs.h:24
#define NODENAME(ckt, nodenum)
Definition: cktdefs.h:137
#define MODEINITTRAN
Definition: cktdefs.h:160
char * errMsg
Definition: main.c:42
IFfrontEnd * SPfrontEnd
Definition: main.c:917
#define NISHOULDREORDER
Definition: cktdefs.h:120
#define FREE(ptr)
Definition: spdefs.h:436
int NIconvTest()
void spSetReal()
#define INITF
Definition: cktdefs.h:155
#define OK
Definition: iferrmsg.h:17
GENERIC * IFuid
Definition: ifsim.h:72
#define MALLOC(x)
Definition: util.h:9
void spGetStat()
#define NULL
Definition: spdefs.h:121
double STATsolveTime
Definition: optdefs.h:31
#define MODEINITSMSIG
Definition: cktdefs.h:159
double STATreorderTime
Definition: optdefs.h:32
#define ERR_WARNING
Definition: ifsim.h:517
#define NIDIDPREORDER
Definition: cktdefs.h:126
int CKTload()
int spFactor()
int NIiter(CKTcircuit *ckt, int maxIter)
Definition: niiter.c:29
#define MODEINITFIX
Definition: cktdefs.h:158
int spOrderAndFactor()
int STATfillIn
Definition: optdefs.h:25
int STATnumIter
Definition: optdefs.h:15
#define E_SINGULAR
Definition: sperror.h:17
void spLoadGmin()
#define E_ITERLIM
Definition: sperror.h:18
static void message(char *instr, char *outstr)
Definition: hcopy.c:13
double STATdecompTime
Definition: optdefs.h:30
#define DEBUGMSG(testargs)
Definition: util.h:34
void spWhereSingular()
void spSolve()
#define MODEINITJCT
Definition: cktdefs.h:157
void spMNA_Preorder()