1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1985 Thomas L. Quarles
4 **********/
5
6 /* CKTsetup(ckt)
7 * this is a driver program to iterate through all the various
8 * setup functions provided for the circuit elements in the
9 * given circuit
10 */
11
12 #include "ngspice/ngspice.h"
13 #include "ngspice/smpdefs.h"
14 #include "ngspice/cktdefs.h"
15 #include "ngspice/devdefs.h"
16 #include "ngspice/sperror.h"
17
18 #ifdef XSPICE
19 #include "ngspice/enh.h"
20 #endif
21
22 #ifdef USE_OMP
23 #include <omp.h>
24 #include "ngspice/cpextern.h"
25 int nthreads;
26 #endif
27
28 #define CKALLOC(var,size,type) \
29 if(size && ((var = TMALLOC(type, size)) == NULL)){\
30 return(E_NOMEM);\
31 }
32
33
34 int
CKTsetup(CKTcircuit * ckt)35 CKTsetup(CKTcircuit *ckt)
36 {
37 int i;
38 int error;
39 #ifdef XSPICE
40 /* gtri - begin - Setup for adding rshunt option resistors */
41 CKTnode *node;
42 int num_nodes;
43 /* gtri - end - Setup for adding rshunt option resistors */
44 #endif
45 SMPmatrix *matrix;
46 ckt->CKTnumStates=0;
47
48 #ifdef WANT_SENSE2
49 if(ckt->CKTsenInfo){
50 error = CKTsenSetup(ckt);
51 if (error)
52 return(error);
53 }
54 #endif
55
56 if (ckt->CKTisSetup)
57 return E_NOCHANGE;
58
59 error = NIinit(ckt);
60 if (error) return(error);
61 ckt->CKTisSetup = 1;
62
63 matrix = ckt->CKTmatrix;
64
65 #ifdef USE_OMP
66 if (!cp_getvar("num_threads", CP_NUM, &nthreads, 0))
67 nthreads = 2;
68
69 omp_set_num_threads(nthreads);
70 /* if (nthreads == 1)
71 printf("OpenMP: %d thread is requested in ngspice\n", nthreads);
72 else
73 printf("OpenMP: %d threads are requested in ngspice\n", nthreads);*/
74 #endif
75
76 #ifdef HAS_PROGREP
77 SetAnalyse("Device Setup", 0);
78 #endif
79
80 /* preserve CKTlastNode before invoking DEVsetup()
81 * so we can check for incomplete CKTdltNNum() invocations
82 * during DEVunsetup() causing an erronous circuit matrix
83 * when reinvoking CKTsetup()
84 */
85 ckt->prev_CKTlastNode = ckt->CKTlastNode;
86
87 for (i=0;i<DEVmaxnum;i++) {
88 if ( DEVices[i] && DEVices[i]->DEVsetup && ckt->CKThead[i] ) {
89 error = DEVices[i]->DEVsetup (matrix, ckt->CKThead[i], ckt,
90 &ckt->CKTnumStates);
91 if(error) return(error);
92 }
93 }
94 for(i=0;i<=MAX(2,ckt->CKTmaxOrder)+1;i++) { /* dctran needs 3 states as minimum */
95 CKALLOC(ckt->CKTstates[i],ckt->CKTnumStates,double);
96 }
97 #ifdef WANT_SENSE2
98 if(ckt->CKTsenInfo){
99 /* to allocate memory to sensitivity structures if
100 * it is not done before */
101
102 error = NIsenReinit(ckt);
103 if(error) return(error);
104 }
105 #endif
106 if(ckt->CKTniState & NIUNINITIALIZED) {
107 error = NIreinit(ckt);
108 if(error) return(error);
109 }
110 #ifdef XSPICE
111 /* gtri - begin - Setup for adding rshunt option resistors */
112
113 if(ckt->enh->rshunt_data.enabled) {
114
115 /* Count number of voltage nodes in circuit */
116 for(num_nodes = 0, node = ckt->CKTnodes; node; node = node->next)
117 if((node->type == SP_VOLTAGE) && (node->number != 0))
118 num_nodes++;
119
120 /* Allocate space for the matrix diagonal data */
121 if(num_nodes > 0) {
122 ckt->enh->rshunt_data.diag =
123 TMALLOC(double *, num_nodes);
124 }
125
126 /* Set the number of nodes in the rshunt data */
127 ckt->enh->rshunt_data.num_nodes = num_nodes;
128
129 /* Get/create matrix diagonal entry following what RESsetup does */
130 for(i = 0, node = ckt->CKTnodes; node; node = node->next) {
131 if((node->type == SP_VOLTAGE) && (node->number != 0)) {
132 ckt->enh->rshunt_data.diag[i] =
133 SMPmakeElt(matrix,node->number,node->number);
134 i++;
135 }
136 }
137
138 }
139
140 /* gtri - end - Setup for adding rshunt option resistors */
141 #endif
142 return(OK);
143 }
144
145 int
CKTunsetup(CKTcircuit * ckt)146 CKTunsetup(CKTcircuit *ckt)
147 {
148 int i, error, e2;
149 CKTnode *node;
150
151 error = OK;
152 if (!ckt->CKTisSetup)
153 return OK;
154
155 for(i=0;i<=ckt->CKTmaxOrder+1;i++) {
156 tfree(ckt->CKTstates[i]);
157 }
158
159 /* added by HT 050802*/
160 for(node=ckt->CKTnodes;node;node=node->next){
161 if(node->icGiven || node->nsGiven) {
162 node->ptr=NULL;
163 }
164 }
165
166 for (i=0;i<DEVmaxnum;i++) {
167 if ( DEVices[i] && DEVices[i]->DEVunsetup && ckt->CKThead[i] ) {
168 e2 = DEVices[i]->DEVunsetup (ckt->CKThead[i], ckt);
169 if (!error && e2)
170 error = e2;
171 }
172 }
173
174 if (ckt->prev_CKTlastNode != ckt->CKTlastNode) {
175 fprintf(stderr, "Internal Error: incomplete CKTunsetup(), this will cause serious problems, please report this issue !\n");
176 controlled_exit(EXIT_FAILURE);
177 }
178 ckt->prev_CKTlastNode = NULL;
179
180 ckt->CKTisSetup = 0;
181 if(error) return(error);
182
183 NIdestroy(ckt);
184 /*
185 if (ckt->CKTmatrix)
186 SMPdestroy(ckt->CKTmatrix);
187 ckt->CKTmatrix = NULL;
188 */
189
190 return OK;
191 }
192