1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1985 Thomas L. Quarles
4
5 This function is obsolete (was used by an old sensitivity analysis)
6 **********/
7
8 /* actually load the current sensitivity
9 * information into the array previously provided
10 */
11
12 #include "ngspice/ngspice.h"
13 #include "ngspice/cktdefs.h"
14 #include "ngspice/smpdefs.h"
15 #include "bjtdefs.h"
16 #include "ngspice/const.h"
17 #include "ngspice/sperror.h"
18 #include "ngspice/ifsim.h"
19 #include "ngspice/suffix.h"
20
21
22 int
BJTsLoad(GENmodel * inModel,CKTcircuit * ckt)23 BJTsLoad(GENmodel *inModel, CKTcircuit *ckt)
24 {
25 BJTmodel *model = (BJTmodel*)inModel;
26 BJTinstance *here;
27 double SaveState0[27];
28 int i;
29 int iparmno;
30 int error;
31 double A0;
32 double DELA;
33 double Apert;
34 double DELAinv;
35 double cb0;
36 double cb;
37 double cc0;
38 double cc;
39 double cx0;
40 double ccpr0;
41 double cepr0;
42 double DcbDp;
43 double DccDp;
44 double DceDp;
45 double DccprDp;
46 double DceprDp;
47 double DcxDp;
48 double DbprmDp;
49 double DcprmDp;
50 double DeprmDp;
51 double gx;
52 double gx0;
53 double tag0;
54 double tag1;
55 double qbe0;
56 double qbe;
57 double qbc0;
58 double qbc;
59 double qcs0;
60 double qcs;
61 double qbx0;
62 double qbx;
63 double DqbeDp = 0.0;
64 double DqbcDp = 0.0;
65 double DqcsDp = 0.0;
66 double DqbxDp = 0.0;
67 double Osxpbe;
68 double Osxpbc;
69 double Osxpcs;
70 double Osxpbx;
71 SENstruct *info;
72
73 tag0 = ckt->CKTag[0];
74 tag1 = ckt->CKTag[1];
75 if(ckt->CKTorder == 1){
76 tag1 = 0;
77 }
78 #ifdef SENSDEBUG
79 printf("BJTsenload \n");
80 printf("CKTtime = %.5e\n",ckt->CKTtime);
81 printf("CKTorder = %.5e\n",ckt->CKTorder);
82 printf("tag0=%.7e,tag1=%.7e\n",tag0,tag1);
83 #endif /* SENSDEBUG */
84 info = ckt->CKTsenInfo;
85
86 info->SENstatus = PERTURBATION;
87
88 /* loop through all the models */
89 for( ; model != NULL; model = BJTnextModel(model)) {
90
91 /* loop through all the instances of the model */
92 for (here = BJTinstances(model); here != NULL ;
93 here=BJTnextInstance(here)) {
94
95 #ifdef SENSDEBUG
96 printf("base = %d , baseprm = %d ,col = %d, colprm = %d\n",
97 here->BJTbaseNode ,here->BJTbasePrimeNode,
98 here->BJTcolNode,here->BJTcolPrimeNode);
99 printf("emit = %d , emitprm = %d ,subst = %d, senparmno = %d\n",
100 here->BJTemitNode ,here->BJTemitPrimeNode,
101 here->BJTsubstNode,here->BJTsenParmNo);
102 #endif /* SENSDEBUG */
103
104
105 /* save the unperturbed values in the state vector */
106 for(i=0; i <= 20; i++){
107 *(SaveState0 + i) = *(ckt->CKTstate0 + here->BJTstate + i);
108 }
109 *(SaveState0 + 21) = *(ckt->CKTstate1 + here->BJTcexbc);
110 *(SaveState0 + 22) = *(ckt->CKTstate2 + here->BJTcexbc);
111 *(SaveState0 + 23) = here->BJTcapbe;
112 *(SaveState0 + 24) = here->BJTcapbc;
113 *(SaveState0 + 25) = here->BJTcapsub;
114 *(SaveState0 + 26) = here->BJTcapbx;
115
116 if(here->BJTsenParmNo == 0) goto next;
117
118 cx0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
119 ccpr0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
120 cepr0 = -cx0 - ccpr0;
121
122 here->BJTsenPertFlag = ON;
123 error = BJTload((GENmodel*)model,ckt);
124 if(error) return(error);
125
126 cb0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
127 cc0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
128 gx0 = *(ckt->CKTstate0 + here->BJTgx);
129
130 qbe0 = *(ckt->CKTstate0 + here->BJTqbe);
131 qbc0 = *(ckt->CKTstate0 + here->BJTqbc);
132 qcs0 = *(ckt->CKTstate0 + here->BJTqsub);
133 qbx0 = *(ckt->CKTstate0 + here->BJTqbx);
134
135 /* perturbation of area */
136
137 A0 = here->BJTarea;
138 DELA = info->SENpertfac * A0;
139 Apert = A0 + DELA;
140 DELAinv = 1.0/DELA;
141 here->BJTsenPertFlag = ON;
142 here->BJTarea = Apert;
143 error = BJTload((GENmodel*)model,ckt);
144 if(error) return(error);
145 here->BJTarea = A0;
146 here->BJTsenPertFlag = OFF;
147
148
149 cb = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
150 cc = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
151 gx = *(ckt->CKTstate0 + here->BJTgx);
152
153 qbe = *(ckt->CKTstate0 + here->BJTqbe);
154 qbc = *(ckt->CKTstate0 + here->BJTqbc);
155 qcs = *(ckt->CKTstate0 + here->BJTqsub);
156 qbx = *(ckt->CKTstate0 + here->BJTqbx);
157
158 /* compute the gradients of currents */
159 DcbDp = (cb - cb0) * DELAinv;
160 DccDp = (cc - cc0) * DELAinv;
161 DceDp = DcbDp + DccDp;
162
163 DccprDp = 0;
164 DceprDp = 0;
165 DcxDp = 0;
166 if(here->BJTcolNode != here->BJTcolPrimeNode)
167 DccprDp = ccpr0 * info->SENpertfac * DELAinv;
168 if(here->BJTemitNode != here->BJTemitPrimeNode)
169 DceprDp = cepr0 * info->SENpertfac * DELAinv;
170 if(here->BJTbaseNode != here->BJTbasePrimeNode){
171 if(gx0) DcxDp = cx0 * DELAinv * (gx-gx0)/gx0;
172 }
173 DbprmDp = DcbDp - DcxDp;
174 DcprmDp = DccDp - DccprDp;
175 DeprmDp = - DceDp - DceprDp;
176
177 DqbeDp = (qbe - qbe0)*DELAinv;
178 DqbcDp = (qbc - qbc0)*DELAinv;
179 DqcsDp = (qcs - qcs0)*DELAinv;
180 DqbxDp = (qbx - qbx0)*DELAinv;
181
182 *(here->BJTdphibedp) = DqbeDp;
183 *(here->BJTdphibcdp) = DqbcDp;
184 *(here->BJTdphisubdp) = DqcsDp;
185 *(here->BJTdphibxdp) = DqbxDp;
186
187 #ifdef SENSDEBUG
188 printf("cb0 = %.7e ,cb = %.7e,\n",cb0,cb);
189 printf("cc0 = %.7e ,cc = %.7e,\n",cc0,cc);
190 printf("ccpr0 = %.7e \n",ccpr0);
191 printf("cepr0 = %.7e \n",cepr0);
192 printf("cx0 = %.7e \n",cx0);
193 printf("qbe0 = %.7e ,qbe = %.7e,\n",qbe0,qbe);
194 printf("qbc0 = %.7e ,qbc = %.7e,\n",qbc0,qbc);
195 printf("qcs0 = %.7e ,qcs = %.7e,\n",qcs0,qcs);
196 printf("qbx0 = %.7e ,qbx = %.7e,\n",qbx0,qbx);
197 printf("\n");
198
199 #endif /* SENSDEBUG */
200
201 if((info->SENmode == TRANSEN) &&
202 (ckt->CKTmode & MODEINITTRAN))
203 goto restore;
204
205 /* load the RHS matrix */
206
207 *(info->SEN_RHS[here->BJTbaseNode] + here->BJTsenParmNo)
208 -= DcxDp;
209 *(info->SEN_RHS[here->BJTbasePrimeNode] + here->BJTsenParmNo)
210 -= DbprmDp;
211 *(info->SEN_RHS[here->BJTcolNode] + here->BJTsenParmNo)
212 -= DccprDp;
213 *(info->SEN_RHS[here->BJTcolPrimeNode] + here->BJTsenParmNo)
214 -= DcprmDp;
215 *(info->SEN_RHS[here->BJTemitNode] + here->BJTsenParmNo)
216 -= DceprDp;
217 *(info->SEN_RHS[here->BJTemitPrimeNode] + here->BJTsenParmNo)
218 -= DeprmDp;
219 #ifdef SENSDEBUG
220 printf("after loading\n");
221 printf("DcxDp=%.7e\n",
222 *(info->SEN_RHS[here->BJTbaseNode] + here->BJTsenParmNo));
223 printf("DcbprmDp=%.7e\n",
224 *(info->SEN_RHS[here->BJTbasePrimeNode] +
225 here->BJTsenParmNo));
226 printf("DccprDp=%.7e\n",
227 *(info->SEN_RHS[here->BJTcolNode] + here->BJTsenParmNo));
228 printf("DcprmDp=%.7e\n",
229 *(info->SEN_RHS[here->BJTcolPrimeNode] +
230 here->BJTsenParmNo));
231 printf("DceprDp=%.7e\n",
232 *(info->SEN_RHS[here->BJTemitNode] +
233 here->BJTsenParmNo));
234 printf("DceprmDp=%.7e\n",
235 *(info->SEN_RHS[here->BJTemitPrimeNode] +
236 here->BJTsenParmNo));
237 #endif /* SENSDEBUG */
238
239 next:
240 if((info->SENmode == DCSEN)||(ckt->CKTmode&MODETRANOP))goto restore;
241 if((info->SENmode == TRANSEN) &&
242 (ckt->CKTmode & MODEINITTRAN))
243 goto restore;
244
245 for(iparmno = 1;iparmno<=info->SENparms;iparmno++){
246 Osxpbe = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbe +
247 8*(iparmno - 1))
248 + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbe +
249 8*(iparmno - 1) + 1);
250
251 Osxpbc = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbc +
252 8*(iparmno - 1))
253 + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbc +
254 8*(iparmno - 1) + 1);
255
256 Osxpcs = tag0 * *(ckt->CKTstate1 + here->BJTsensxpsub +
257 8*(iparmno - 1))
258 + tag1 * *(ckt->CKTstate1 + here->BJTsensxpsub +
259 8*(iparmno - 1) + 1);
260
261 Osxpbx = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbx +
262 8*(iparmno - 1))
263 + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbx +
264 8*(iparmno - 1) + 1);
265 #ifdef SENSDEBUG
266 printf("iparmno=%d\n",iparmno);
267 printf("Osxpbe=%.7e,Osxpbc=%.7e\n",Osxpbe,Osxpbc);
268 printf("Osxpcs=%.7e,Osxpbx=%.7e\n",Osxpcs,Osxpbx);
269 printf("sxpbe=%.7e,sdbe=%.7e\n",
270 *(ckt->CKTstate1 + here->BJTsensxpbe + 8*(iparmno - 1))
271 ,*(ckt->CKTstate1 + here->BJTsensxpbe +
272 8*(iparmno - 1) + 1));
273 printf("sxpbc=%.7e,sdbc=%.7e\n",
274 *(ckt->CKTstate1 + here->BJTsensxpbc + 8*(iparmno - 1))
275 ,*(ckt->CKTstate1 + here->BJTsensxpbc +
276 8*(iparmno - 1) + 1));
277 printf("\n");
278 #endif /* SENSDEBUG */
279
280 if(iparmno == here->BJTsenParmNo){
281 Osxpbe = Osxpbe - tag0 * DqbeDp;
282 Osxpbc = Osxpbc - tag0 * DqbcDp;
283 Osxpcs = Osxpcs - tag0 * DqcsDp;
284 Osxpbx = Osxpbx - tag0 * DqbxDp;
285 }
286
287 #ifdef SENSDEBUG
288
289 printf("Osxpbe=%.7e,Osxpbc=%.7e\n",Osxpbe,Osxpbc);
290 printf("Osxpcs=%.7e,Osxpbx=%.7e\n",Osxpcs,Osxpbx);
291 #endif /* SENSDEBUG */
292
293 *(info->SEN_RHS[here->BJTbaseNode] + iparmno)
294 += model->BJTtype * Osxpbx;
295
296 *(info->SEN_RHS[here->BJTbasePrimeNode] + iparmno)
297 += model->BJTtype * (Osxpbe + Osxpbc);
298
299 *(info->SEN_RHS[here->BJTcolPrimeNode] + iparmno)
300 -= model->BJTtype * (Osxpbc + Osxpcs + Osxpbx );
301
302 *(info->SEN_RHS[here->BJTemitPrimeNode] + iparmno)
303 -= model->BJTtype * Osxpbe;
304
305 *(info->SEN_RHS[here->BJTsubstNode] + iparmno)
306 += model->BJTtype * Osxpcs;
307
308 }
309
310
311 /* put the unperturbed values back into the state vector */
312 restore:
313 for(i=0; i <= 20; i++){
314 *(ckt->CKTstate0 + here->BJTstate + i) = *(SaveState0 + i);
315 }
316 *(ckt->CKTstate1 + here->BJTcexbc) = *(SaveState0 + 21);
317 here->BJTcapbe = *(SaveState0 + 23) ;
318 here->BJTcapbc = *(SaveState0 + 24) ;
319 here->BJTcapsub = *(SaveState0 + 25) ;
320 here->BJTcapbx = *(SaveState0 + 26) ;
321
322 }
323 }
324 info->SENstatus = NORMAL;
325 #ifdef SENSDEBUG
326 printf("BJTsenload end\n");
327 #endif /* SENSDEBUG */
328 return(OK);
329 }
330