1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1985 Thomas L. Quarles
4 Modified 1999 Emmanuel Rouat
5 **********/
6
7 /*
8 * NIacIter(ckt)
9 *
10 * This subroutine performs the actual numerical iteration.
11 * It uses the sparse matrix stored in the NIstruct by NIinit,
12 * along with the matrix loading program, the load data, the
13 * convergence test function, and the convergence parameters
14 * - return value is non-zero for convergence failure
15 */
16
17 #include "ngspice/ngspice.h"
18 #include "ngspice/trandefs.h"
19 #include "ngspice/cktdefs.h"
20 #include "ngspice/sperror.h"
21
22
23 int
NIacIter(CKTcircuit * ckt)24 NIacIter(CKTcircuit *ckt)
25 {
26 int error;
27 int ignore;
28 double startTime;
29
30 retry:
31 ckt->CKTnoncon=0;
32
33 error = CKTacLoad(ckt);
34 if(error) return(error);
35
36 if(ckt->CKTniState & NIACSHOULDREORDER) {
37 startTime = SPfrontEnd->IFseconds();
38 error = SMPcReorder(ckt->CKTmatrix,ckt->CKTpivotAbsTol,
39 ckt->CKTpivotRelTol,&ignore);
40 ckt->CKTstat->STATreorderTime +=
41 SPfrontEnd->IFseconds()- startTime;
42 ckt->CKTniState &= ~NIACSHOULDREORDER;
43 if(error != 0) {
44 /* either singular equations or no memory, in either case,
45 * let caller handle problem
46 */
47 return(error);
48 }
49 } else {
50 startTime = SPfrontEnd->IFseconds();
51 error = SMPcLUfac(ckt->CKTmatrix,ckt->CKTpivotAbsTol);
52 ckt->CKTstat->STATdecompTime +=
53 SPfrontEnd->IFseconds()-startTime;
54 if(error != 0) {
55 if(error == E_SINGULAR) {
56 /* the problem is that the matrix can't be solved with the
57 * current LU factorization. Maybe if we reload and
58 * try to reorder again it will help...
59 */
60 ckt->CKTniState |= NIACSHOULDREORDER;
61 goto retry;
62 }
63 return(error); /* can't handle E_BADMATRIX, so let caller */
64 }
65 }
66 startTime = SPfrontEnd->IFseconds();
67 SMPcSolve(ckt->CKTmatrix,ckt->CKTrhs,
68 ckt->CKTirhs, ckt->CKTrhsSpare,
69 ckt->CKTirhsSpare);
70 ckt->CKTstat->STATsolveTime += SPfrontEnd->IFseconds() - startTime;
71
72 ckt->CKTrhs[0] = 0;
73 ckt->CKTrhsSpare[0] = 0;
74 ckt->CKTrhsOld[0] = 0;
75 ckt->CKTirhs[0] = 0;
76 ckt->CKTirhsSpare[0] = 0;
77 ckt->CKTirhsOld[0] = 0;
78
79 SWAP(double *, ckt->CKTirhs, ckt->CKTirhsOld);
80
81 SWAP(double *, ckt->CKTrhs, ckt->CKTrhsOld);
82
83 return(OK);
84 }
85